| 1 | Index: django/contrib/auth/backends.py
|
|---|
| 2 | ===================================================================
|
|---|
| 3 | --- django/contrib/auth/backends.py (revision 6184)
|
|---|
| 4 | +++ django/contrib/auth/backends.py (working copy)
|
|---|
| 5 | @@ -1,3 +1,4 @@
|
|---|
| 6 | +from django.db import connection, models
|
|---|
| 7 | from django.contrib.auth.models import User
|
|---|
| 8 |
|
|---|
| 9 | class ModelBackend:
|
|---|
| 10 | @@ -14,6 +15,51 @@
|
|---|
| 11 | except User.DoesNotExist:
|
|---|
| 12 | return None
|
|---|
| 13 |
|
|---|
| 14 | + def get_group_permissions(self, user_obj):
|
|---|
| 15 | + "Returns a list of permission strings that this user has through his/her groups."
|
|---|
| 16 | + if not hasattr(user_obj, '_group_perm_cache'):
|
|---|
| 17 | + cursor = connection.cursor()
|
|---|
| 18 | + # The SQL below works out to the following, after DB quoting:
|
|---|
| 19 | + # cursor.execute("""
|
|---|
| 20 | + # SELECT ct."app_label", p."codename"
|
|---|
| 21 | + # FROM "auth_permission" p, "auth_group_permissions" gp, "auth_user_groups" ug, "django_content_type" ct
|
|---|
| 22 | + # WHERE p."id" = gp."permission_id"
|
|---|
| 23 | + # AND gp."group_id" = ug."group_id"
|
|---|
| 24 | + # AND ct."id" = p."content_type_id"
|
|---|
| 25 | + # AND ug."user_id" = %s, [self.id])
|
|---|
| 26 | + qn = connection.ops.quote_name
|
|---|
| 27 | + sql = """
|
|---|
| 28 | + SELECT ct.%s, p.%s
|
|---|
| 29 | + FROM %s p, %s gp, %s ug, %s ct
|
|---|
| 30 | + WHERE p.%s = gp.%s
|
|---|
| 31 | + AND gp.%s = ug.%s
|
|---|
| 32 | + AND ct.%s = p.%s
|
|---|
| 33 | + AND ug.%s = %%s""" % (
|
|---|
| 34 | + qn('app_label'), qn('codename'),
|
|---|
| 35 | + qn('auth_permission'), qn('auth_group_permissions'),
|
|---|
| 36 | + qn('auth_user_groups'), qn('django_content_type'),
|
|---|
| 37 | + qn('id'), qn('permission_id'),
|
|---|
| 38 | + qn('group_id'), qn('group_id'),
|
|---|
| 39 | + qn('id'), qn('content_type_id'),
|
|---|
| 40 | + qn('user_id'),)
|
|---|
| 41 | + cursor.execute(sql, [user_obj.id])
|
|---|
| 42 | + user_obj._group_perm_cache = set(["%s.%s" % (row[0], row[1]) for row in cursor.fetchall()])
|
|---|
| 43 | + return user_obj._group_perm_cache
|
|---|
| 44 | +
|
|---|
| 45 | + def get_all_permissions(self, user_obj):
|
|---|
| 46 | + if not hasattr(user_obj, '_perm_cache'):
|
|---|
| 47 | + user_obj._perm_cache = set([u"%s.%s" % (p.content_type.app_label, p.codename) for p in user_obj.user_permissions.select_related()])
|
|---|
| 48 | + user_obj._perm_cache.update(self.get_group_permissions(user_obj))
|
|---|
| 49 | + return user_obj._perm_cache
|
|---|
| 50 | +
|
|---|
| 51 | + def has_perm(self, user_obj, perm):
|
|---|
| 52 | + return perm in self.get_all_permissions(user_obj)
|
|---|
| 53 | +
|
|---|
| 54 | + def has_module_perms(self, user_obj, app_label):
|
|---|
| 55 | + return bool(len([p for p in self.get_all_permissions(user_obj) if p[:p.index('.')] == app_label]))
|
|---|
| 56 | +
|
|---|
| 57 | +
|
|---|
| 58 | +
|
|---|
| 59 | def get_user(self, user_id):
|
|---|
| 60 | try:
|
|---|
| 61 | return User.objects.get(pk=user_id)
|
|---|
| 62 | Index: django/contrib/auth/models.py
|
|---|
| 63 | ===================================================================
|
|---|
| 64 | --- django/contrib/auth/models.py (revision 6184)
|
|---|
| 65 | +++ django/contrib/auth/models.py (working copy)
|
|---|
| 66 | @@ -1,3 +1,4 @@
|
|---|
| 67 | +from django.contrib.auth import get_backends
|
|---|
| 68 | from django.core import validators
|
|---|
| 69 | from django.core.exceptions import ImproperlyConfigured
|
|---|
| 70 | from django.db import connection, models
|
|---|
| 71 | @@ -177,49 +178,41 @@
|
|---|
| 72 | return self.password != UNUSABLE_PASSWORD
|
|---|
| 73 |
|
|---|
| 74 | def get_group_permissions(self):
|
|---|
| 75 | - "Returns a list of permission strings that this user has through his/her groups."
|
|---|
| 76 | - if not hasattr(self, '_group_perm_cache'):
|
|---|
| 77 | - cursor = connection.cursor()
|
|---|
| 78 | - # The SQL below works out to the following, after DB quoting:
|
|---|
| 79 | - # cursor.execute("""
|
|---|
| 80 | - # SELECT ct."app_label", p."codename"
|
|---|
| 81 | - # FROM "auth_permission" p, "auth_group_permissions" gp, "auth_user_groups" ug, "django_content_type" ct
|
|---|
| 82 | - # WHERE p."id" = gp."permission_id"
|
|---|
| 83 | - # AND gp."group_id" = ug."group_id"
|
|---|
| 84 | - # AND ct."id" = p."content_type_id"
|
|---|
| 85 | - # AND ug."user_id" = %s, [self.id])
|
|---|
| 86 | - qn = connection.ops.quote_name
|
|---|
| 87 | - sql = """
|
|---|
| 88 | - SELECT ct.%s, p.%s
|
|---|
| 89 | - FROM %s p, %s gp, %s ug, %s ct
|
|---|
| 90 | - WHERE p.%s = gp.%s
|
|---|
| 91 | - AND gp.%s = ug.%s
|
|---|
| 92 | - AND ct.%s = p.%s
|
|---|
| 93 | - AND ug.%s = %%s""" % (
|
|---|
| 94 | - qn('app_label'), qn('codename'),
|
|---|
| 95 | - qn('auth_permission'), qn('auth_group_permissions'),
|
|---|
| 96 | - qn('auth_user_groups'), qn('django_content_type'),
|
|---|
| 97 | - qn('id'), qn('permission_id'),
|
|---|
| 98 | - qn('group_id'), qn('group_id'),
|
|---|
| 99 | - qn('id'), qn('content_type_id'),
|
|---|
| 100 | - qn('user_id'),)
|
|---|
| 101 | - cursor.execute(sql, [self.id])
|
|---|
| 102 | - self._group_perm_cache = set(["%s.%s" % (row[0], row[1]) for row in cursor.fetchall()])
|
|---|
| 103 | - return self._group_perm_cache
|
|---|
| 104 | + """
|
|---|
| 105 | + Returns a list of permission strings that this user has through his/her groups.
|
|---|
| 106 | + This method queries the available backends.
|
|---|
| 107 | + """
|
|---|
| 108 | + group_permissions = set([])
|
|---|
| 109 | + for backend in get_backends():
|
|---|
| 110 | + # Backend does not support this method, so skip it
|
|---|
| 111 | + if not hasattr(backend, "get_group_permissions"): continue
|
|---|
| 112 | + group_permissions.update(backend.get_group_permissions(self))
|
|---|
| 113 | + return group_permissions
|
|---|
| 114 |
|
|---|
| 115 | def get_all_permissions(self):
|
|---|
| 116 | - if not hasattr(self, '_perm_cache'):
|
|---|
| 117 | - self._perm_cache = set([u"%s.%s" % (p.content_type.app_label, p.codename) for p in self.user_permissions.select_related()])
|
|---|
| 118 | - self._perm_cache.update(self.get_group_permissions())
|
|---|
| 119 | - return self._perm_cache
|
|---|
| 120 | + permissions = set([])
|
|---|
| 121 | + for backend in get_backends():
|
|---|
| 122 | + # Backend does not support this method, so skip it
|
|---|
| 123 | + if not hasattr(backend, "get_all_permissions"): continue
|
|---|
| 124 | + permissions.update(backend.get_all_permissions(self))
|
|---|
| 125 | + return permissions
|
|---|
| 126 |
|
|---|
| 127 | def has_perm(self, perm):
|
|---|
| 128 | - "Returns True if the user has the specified permission."
|
|---|
| 129 | + """
|
|---|
| 130 | + Returns True if the user has the specified permission.
|
|---|
| 131 | + This method queries the available backends and stops on
|
|---|
| 132 | + the first "True".
|
|---|
| 133 | + """
|
|---|
| 134 | if not self.is_active:
|
|---|
| 135 | return False
|
|---|
| 136 | if self.is_superuser:
|
|---|
| 137 | return True
|
|---|
| 138 | - return perm in self.get_all_permissions()
|
|---|
| 139 | + for backend in get_backends():
|
|---|
| 140 | + # Backend does not support this method, so skip it
|
|---|
| 141 | + if not hasattr(backend, "has_perm"): continue
|
|---|
| 142 | + if backend.has_perm(self, perm):
|
|---|
| 143 | + return True
|
|---|
| 144 | + return False
|
|---|
| 145 |
|
|---|
| 146 | def has_perms(self, perm_list):
|
|---|
| 147 | "Returns True if the user has each of the specified permissions."
|
|---|
| 148 | @@ -229,12 +222,21 @@
|
|---|
| 149 | return True
|
|---|
| 150 |
|
|---|
| 151 | def has_module_perms(self, app_label):
|
|---|
| 152 | - "Returns True if the user has any permissions in the given app label."
|
|---|
| 153 | + """
|
|---|
| 154 | + Returns True if the user has any permissions in the given app label.
|
|---|
| 155 | + This method queries the available backends and stops on
|
|---|
| 156 | + the first "True".
|
|---|
| 157 | + """
|
|---|
| 158 | if not self.is_active:
|
|---|
| 159 | return False
|
|---|
| 160 | if self.is_superuser:
|
|---|
| 161 | return True
|
|---|
| 162 | - return bool(len([p for p in self.get_all_permissions() if p[:p.index('.')] == app_label]))
|
|---|
| 163 | + for backend in get_backends():
|
|---|
| 164 | + # Backend does not support this method, so skip it
|
|---|
| 165 | + if not hasattr(backend, "has_module_perms"): continue
|
|---|
| 166 | + if backend.has_module_perms(self, app_label):
|
|---|
| 167 | + return True
|
|---|
| 168 | + return False
|
|---|
| 169 |
|
|---|
| 170 | def get_and_delete_messages(self):
|
|---|
| 171 | messages = []
|
|---|
| 172 | Index: docs/authentication.txt
|
|---|
| 173 | ===================================================================
|
|---|
| 174 | --- docs/authentication.txt (revision 6184)
|
|---|
| 175 | +++ docs/authentication.txt (working copy)
|
|---|
| 176 | @@ -1041,3 +1041,26 @@
|
|---|
| 177 | return User.objects.get(pk=user_id)
|
|---|
| 178 | except User.DoesNotExist:
|
|---|
| 179 | return None
|
|---|
| 180 | +
|
|---|
| 181 | +Optionally the Backend allows you to specify any of the permission methods of
|
|---|
| 182 | +the ``User`` object (except from ``has_perms`` which calls ``has_perm`` for each
|
|---|
| 183 | +perm in the list, and ``has_perm`` can be specified in the backend).
|
|---|
| 184 | +This will allow your backend to handle the permissions, if one backend return
|
|---|
| 185 | +``True`` in a permission check, the user will have the permission.
|
|---|
| 186 | +
|
|---|
| 187 | +Here is an sample implementation for ``has_perm`` extending the above exmaple::
|
|---|
| 188 | +
|
|---|
| 189 | + # The permission functions all take the user_obj as first (besides the self of
|
|---|
| 190 | + # the backend, of course) argument and the rest
|
|---|
| 191 | + # is as you would call it with ``User.*``
|
|---|
| 192 | + def has_perm(self, user_obj, perm):
|
|---|
| 193 | + # we give the user admin the right to do everything.
|
|---|
| 194 | + if user_obj.username == "admin":
|
|---|
| 195 | + return True
|
|---|
| 196 | + else:
|
|---|
| 197 | + return False
|
|---|
| 198 | +
|
|---|
| 199 | +A full implementation can be found in ``django/contrib/auth/backends.py`` _, which is the
|
|---|
| 200 | +default backend and queries the ``auth_permission``-table most of the time.
|
|---|
| 201 | +
|
|---|
| 202 | +.. _django/contrib/auth/backends.py: http://code.djangoproject.com/browser/django/trunk/django/contrib/auth/backends.py
|
|---|