10
10
from django.utils.hashcompat import md5_constructor, sha_constructor
11
11
from django.utils.translation import ugettext_lazy as _
13
14
UNUSABLE_PASSWORD = '!' # This will never be a valid hash
18
from sets import Set as set # Python 2.3 fallback
20
16
def get_hexdigest(algorithm, salt, raw_password):
22
18
Returns a string of the hexdigest of the given plaintext password and salt
47
43
class SiteProfileNotAvailable(Exception):
46
class PermissionManager(models.Manager):
47
def get_by_natural_key(self, codename, app_label, model):
50
content_type=ContentType.objects.get_by_natural_key(app_label, model)
50
53
class Permission(models.Model):
51
54
"""The permissions system provides a way to assign permissions to specific users and groups of users.
63
66
name = models.CharField(_('name'), max_length=50)
64
67
content_type = models.ForeignKey(ContentType)
65
68
codename = models.CharField(_('codename'), max_length=100)
69
objects = PermissionManager()
68
72
verbose_name = _('permission')
69
73
verbose_name_plural = _('permissions')
70
74
unique_together = (('content_type', 'codename'),)
71
ordering = ('content_type__app_label', 'codename')
75
ordering = ('content_type__app_label', 'content_type__model', 'codename')
73
77
def __unicode__(self):
74
78
return u"%s | %s | %s" % (
76
80
unicode(self.content_type),
77
81
unicode(self.name))
83
def natural_key(self):
84
return (self.codename,) + self.content_type.natural_key()
85
natural_key.dependencies = ['contenttypes.contenttype']
79
87
class Group(models.Model):
80
88
"""Groups are a generic way of categorizing users to apply permissions, or some other label, to those users. A user can belong to any number of groups.
96
104
class UserManager(models.Manager):
97
105
def create_user(self, username, email, password=None):
98
"Creates and saves a User with the given username, e-mail and password."
107
Creates and saves a User with the given username, e-mail and password.
99
110
now = datetime.datetime.now()
100
user = self.model(None, username, '', '', email.strip().lower(), 'placeholder', False, True, False, now, now)
112
# Normalize the address by lowercasing the domain part of the email
115
email_name, domain_part = email.strip().split('@', 1)
119
email = '@'.join([email_name, domain_part.lower()])
121
user = self.model(username=username, email=email, is_staff=False,
122
is_active=True, is_superuser=False, last_login=now,
102
126
user.set_password(password)
104
128
user.set_unusable_password()
129
user.save(using=self._db)
108
132
def create_superuser(self, username, email, password):
120
144
from random import choice
121
145
return ''.join([choice(allowed_chars) for i in range(length)])
148
# A few helper functions for common logic between User and AnonymousUser.
149
def _user_get_all_permissions(user, obj):
151
anon = user.is_anonymous()
152
for backend in auth.get_backends():
153
if not anon or backend.supports_anonymous_user:
154
if hasattr(backend, "get_all_permissions"):
156
if backend.supports_object_permissions:
158
backend.get_all_permissions(user, obj)
161
permissions.update(backend.get_all_permissions(user))
165
def _user_has_perm(user, perm, obj):
166
anon = user.is_anonymous()
167
for backend in auth.get_backends():
168
if not anon or backend.supports_anonymous_user:
169
if hasattr(backend, "has_perm"):
171
if (backend.supports_object_permissions and
172
backend.has_perm(user, perm, obj)):
175
if backend.has_perm(user, perm):
180
def _user_has_module_perms(user, app_label):
181
anon = user.is_anonymous()
182
for backend in auth.get_backends():
183
if not anon or backend.supports_anonymous_user:
184
if hasattr(backend, "has_module_perms"):
185
if backend.has_module_perms(user, app_label):
123
190
class User(models.Model):
124
"""Users within the Django authentication system are represented by this model.
192
Users within the Django authentication system are represented by this model.
126
194
Username and password are required. Other fields are optional.
128
username = models.CharField(_('username'), max_length=30, unique=True, help_text=_("Required. 30 characters or fewer. Alphanumeric characters only (letters, digits and underscores)."))
196
username = models.CharField(_('username'), max_length=30, unique=True, help_text=_("Required. 30 characters or fewer. Letters, numbers and @/./+/-/_ characters"))
129
197
first_name = models.CharField(_('first name'), max_length=30, blank=True)
130
198
last_name = models.CharField(_('last name'), max_length=30, blank=True)
131
199
email = models.EmailField(_('e-mail address'), blank=True)
151
219
return "/users/%s/" % urllib.quote(smart_str(self.username))
153
221
def is_anonymous(self):
154
"Always returns False. This is a way of comparing User objects to anonymous users."
223
Always returns False. This is a way of comparing User objects to
157
228
def is_authenticated(self):
158
"""Always return True. This is a way to tell if the user has been authenticated in templates.
230
Always return True. This is a way to tell if the user has been
231
authenticated in templates.
194
267
def has_usable_password(self):
195
268
return self.password != UNUSABLE_PASSWORD
197
def get_group_permissions(self):
270
def get_group_permissions(self, obj=None):
199
272
Returns a list of permission strings that this user has through
200
273
his/her groups. This method queries all available auth backends.
274
If an object is passed in, only permissions matching this object
202
277
permissions = set()
203
278
for backend in auth.get_backends():
204
279
if hasattr(backend, "get_group_permissions"):
205
permissions.update(backend.get_group_permissions(self))
208
def get_all_permissions(self):
210
for backend in auth.get_backends():
211
if hasattr(backend, "get_all_permissions"):
212
permissions.update(backend.get_all_permissions(self))
215
def has_perm(self, perm):
281
if backend.supports_object_permissions:
283
backend.get_group_permissions(self, obj)
286
permissions.update(backend.get_group_permissions(self))
289
def get_all_permissions(self, obj=None):
290
return _user_get_all_permissions(self, obj)
292
def has_perm(self, perm, obj=None):
217
294
Returns True if the user has the specified permission. This method
218
295
queries all available auth backends, but returns immediately if any
219
296
backend returns True. Thus, a user who has permission from a single
220
auth backend is assumed to have permission in general.
297
auth backend is assumed to have permission in general. If an object
298
is provided, permissions for this specific object are checked.
222
300
# Inactive users have no permissions.
223
301
if not self.is_active:
230
308
# Otherwise we need to check the backends.
231
for backend in auth.get_backends():
232
if hasattr(backend, "has_perm"):
233
if backend.has_perm(self, perm):
309
return _user_has_perm(self, perm, obj)
237
def has_perms(self, perm_list):
238
"""Returns True if the user has each of the specified permissions."""
311
def has_perms(self, perm_list, obj=None):
313
Returns True if the user has each of the specified permissions.
314
If object is passed, it checks if the user has all required perms
239
317
for perm in perm_list:
240
if not self.has_perm(perm):
318
if not self.has_perm(perm, obj):
252
330
if self.is_superuser:
255
for backend in auth.get_backends():
256
if hasattr(backend, "has_module_perms"):
257
if backend.has_module_perms(self, app_label):
333
return _user_has_module_perms(self, app_label)
261
335
def get_and_delete_messages(self):
278
352
if not hasattr(self, '_profile_cache'):
279
353
from django.conf import settings
280
354
if not getattr(settings, 'AUTH_PROFILE_MODULE', False):
281
raise SiteProfileNotAvailable
355
raise SiteProfileNotAvailable('You need to set AUTH_PROFILE_MO'
356
'DULE in your project settings')
283
358
app_label, model_name = settings.AUTH_PROFILE_MODULE.split('.')
360
raise SiteProfileNotAvailable('app_label and model_name should'
361
' be separated by a dot in the AUTH_PROFILE_MODULE set'
284
365
model = models.get_model(app_label, model_name)
285
self._profile_cache = model._default_manager.get(user__id__exact=self.id)
367
raise SiteProfileNotAvailable('Unable to load the profile '
368
'model, check AUTH_PROFILE_MODULE in your project sett'
370
self._profile_cache = model._default_manager.using(self._state.db).get(user__id__exact=self.id)
286
371
self._profile_cache.user = self
287
372
except (ImportError, ImproperlyConfigured):
288
373
raise SiteProfileNotAvailable
289
374
return self._profile_cache
376
def _get_message_set(self):
378
warnings.warn('The user messaging API is deprecated. Please update'
379
' your code to use the new messages framework.',
380
category=PendingDeprecationWarning)
381
return self._message_set
382
message_set = property(_get_message_set)
291
384
class Message(models.Model):
293
386
The message system is a lightweight way to queue messages for given
350
443
return self._user_permissions
351
444
user_permissions = property(_get_user_permissions)
353
def has_perm(self, perm):
356
def has_perms(self, perm_list):
446
def get_group_permissions(self, obj=None):
449
def get_all_permissions(self, obj=None):
450
return _user_get_all_permissions(self, obj=obj)
452
def has_perm(self, perm, obj=None):
453
return _user_has_perm(self, perm, obj=obj)
455
def has_perms(self, perm_list, obj=None):
456
for perm in perm_list:
457
if not self.has_perm(perm, obj):
359
461
def has_module_perms(self, module):
462
return _user_has_module_perms(self, module)
362
464
def get_and_delete_messages(self):