Code

Ticket #3011: #3011-extendable_auth_user-1.4.diff

File #3011-extendable_auth_user-1.4.diff, 35.8 KB (added by Kronuz, 2 years ago)

Updated for django 1.4

Line 
1diff --git a/django/contrib/admin/sites.py b/django/contrib/admin/sites.py
2index 83a0869..0cc92e3 100644
3--- django/contrib/admin/sites.py
4+++ django/contrib/admin/sites.py
5@@ -1,7 +1,6 @@
6 from functools import update_wrapper
7 from django import http
8 from django.contrib.admin import ModelAdmin, actions
9-from django.contrib.admin.forms import AdminAuthenticationForm
10 from django.contrib.auth import REDIRECT_FIELD_NAME
11 from django.contrib.contenttypes import views as contenttype_views
12 from django.views.decorators.csrf import csrf_protect
13@@ -307,6 +306,7 @@ class AdminSite(object):
14         Displays the login form for the given HttpRequest.
15         """
16         from django.contrib.auth.views import login
17+        from django.contrib.admin.forms import AdminAuthenticationForm
18         context = {
19             'title': _('Log in'),
20             'app_path': request.get_full_path(),
21diff --git a/django/contrib/auth/base.py b/django/contrib/auth/base.py
22new file mode 100644
23index 0000000..c919822
24--- /dev/null
25+++ django/contrib/auth/base.py
26@@ -0,0 +1,449 @@
27+import urllib
28+
29+from django.core.exceptions import ImproperlyConfigured
30+from django.core.mail import send_mail
31+from django.db import models
32+from django.db.models.manager import EmptyManager
33+from django.utils.crypto import get_random_string
34+from django.utils.encoding import smart_str
35+from django.utils.translation import ugettext_lazy as _
36+from django.utils import timezone
37+
38+from django.contrib import auth
39+# UNUSABLE_PASSWORD is still imported here for backwards compatibility
40+from django.contrib.auth.hashers import (
41+    check_password, make_password, is_password_usable, UNUSABLE_PASSWORD)
42+from django.contrib.auth.signals import user_logged_in
43+from django.contrib.contenttypes.models import ContentType
44+
45+
46+def update_last_login(sender, user, **kwargs):
47+    """
48+    A signal receiver which updates the last_login date for
49+    the user logging in.
50+    """
51+    user.last_login = timezone.now()
52+    user.save()
53+user_logged_in.connect(update_last_login)
54+
55+
56+class SiteProfileNotAvailable(Exception):
57+    pass
58+
59+
60+class PermissionManager(models.Manager):
61+    def get_by_natural_key(self, codename, app_label, model):
62+        return self.get(
63+            codename=codename,
64+            content_type=ContentType.objects.get_by_natural_key(app_label,
65+                                                                model),
66+        )
67+
68+
69+class Permission(models.Model):
70+    """
71+    The permissions system provides a way to assign permissions to specific
72+    users and groups of users.
73+
74+    The permission system is used by the Django admin site, but may also be
75+    useful in your own code. The Django admin site uses permissions as follows:
76+
77+        - The "add" permission limits the user's ability to view the "add" form
78+          and add an object.
79+        - The "change" permission limits a user's ability to view the change
80+          list, view the "change" form and change an object.
81+        - The "delete" permission limits the ability to delete an object.
82+
83+    Permissions are set globally per type of object, not per specific object
84+    instance. It is possible to say "Mary may change news stories," but it's
85+    not currently possible to say "Mary may change news stories, but only the
86+    ones she created herself" or "Mary may only change news stories that have a
87+    certain status or publication date."
88+
89+    Three basic permissions -- add, change and delete -- are automatically
90+    created for each Django model.
91+    """
92+    name = models.CharField(_('name'), max_length=50)
93+    content_type = models.ForeignKey(ContentType)
94+    codename = models.CharField(_('codename'), max_length=100)
95+    objects = PermissionManager()
96+
97+    class Meta:
98+        verbose_name = _('permission')
99+        verbose_name_plural = _('permissions')
100+        unique_together = (('content_type', 'codename'),)
101+        ordering = ('content_type__app_label', 'content_type__model',
102+                    'codename')
103+
104+    def __unicode__(self):
105+        return u"%s | %s | %s" % (
106+            unicode(self.content_type.app_label),
107+            unicode(self.content_type),
108+            unicode(self.name))
109+
110+    def natural_key(self):
111+        return (self.codename,) + self.content_type.natural_key()
112+    natural_key.dependencies = ['contenttypes.contenttype']
113+
114+
115+class Group(models.Model):
116+    """
117+    Groups are a generic way of categorizing users to apply permissions, or
118+    some other label, to those users. A user can belong to any number of
119+    groups.
120+
121+    A user in a group automatically has all the permissions granted to that
122+    group. For example, if the group Site editors has the permission
123+    can_edit_home_page, any user in that group will have that permission.
124+
125+    Beyond permissions, groups are a convenient way to categorize users to
126+    apply some label, or extended functionality, to them. For example, you
127+    could create a group 'Special users', and you could write code that would
128+    do special things to those users -- such as giving them access to a
129+    members-only portion of your site, or sending them members-only email
130+    messages.
131+    """
132+    name = models.CharField(_('name'), max_length=80, unique=True)
133+    permissions = models.ManyToManyField(Permission,
134+        verbose_name=_('permissions'), blank=True)
135+
136+    class Meta:
137+        verbose_name = _('group')
138+        verbose_name_plural = _('groups')
139+
140+    def __unicode__(self):
141+        return self.name
142+
143+
144+class UserManager(models.Manager):
145+    def create_user(self, username, email=None, password=None):
146+        """
147+        Creates and saves a User with the given username, email and password.
148+        """
149+        now = timezone.now()
150+
151+        # Normalize the address by lowercasing the domain part of the email
152+        # address.
153+        email = email or ''
154+        try:
155+            email_name, domain_part = email.strip().split('@', 1)
156+        except ValueError:
157+            pass
158+        else:
159+            email = '@'.join([email_name, domain_part.lower()])
160+
161+        user = self.model(username=username, email=email, is_staff=False,
162+                         is_active=True, is_superuser=False, last_login=now,
163+                         date_joined=now)
164+
165+        user.set_password(password)
166+        user.save(using=self._db)
167+        return user
168+
169+    def create_superuser(self, username, email, password):
170+        u = self.create_user(username, email, password)
171+        u.is_staff = True
172+        u.is_active = True
173+        u.is_superuser = True
174+        u.save(using=self._db)
175+        return u
176+
177+    def make_random_password(self, length=10,
178+                             allowed_chars='abcdefghjkmnpqrstuvwxyz'
179+                                           'ABCDEFGHJKLMNPQRSTUVWXYZ'
180+                                           '23456789'):
181+        """
182+        Generates a random password with the given length and given
183+        allowed_chars. Note that the default value of allowed_chars does not
184+        have "I" or "O" or letters and digits that look similar -- just to
185+        avoid confusion.
186+        """
187+        return get_random_string(length, allowed_chars)
188+
189+
190+# A few helper functions for common logic between User and AnonymousUser.
191+def _user_get_all_permissions(user, obj):
192+    permissions = set()
193+    for backend in auth.get_backends():
194+        if hasattr(backend, "get_all_permissions"):
195+            if obj is not None:
196+                permissions.update(backend.get_all_permissions(user, obj))
197+            else:
198+                permissions.update(backend.get_all_permissions(user))
199+    return permissions
200+
201+
202+def _user_has_perm(user, perm, obj):
203+    anon = user.is_anonymous()
204+    active = user.is_active
205+    for backend in auth.get_backends():
206+        if anon or active or backend.supports_inactive_user:
207+            if hasattr(backend, "has_perm"):
208+                if obj is not None:
209+                    if backend.has_perm(user, perm, obj):
210+                            return True
211+                else:
212+                    if backend.has_perm(user, perm):
213+                        return True
214+    return False
215+
216+
217+def _user_has_module_perms(user, app_label):
218+    anon = user.is_anonymous()
219+    active = user.is_active
220+    for backend in auth.get_backends():
221+        if anon or active or backend.supports_inactive_user:
222+            if hasattr(backend, "has_module_perms"):
223+                if backend.has_module_perms(user, app_label):
224+                    return True
225+    return False
226+
227+
228+class UserTemplate(models.Model):
229+    """
230+    Users within the Django authentication system are represented by this
231+    model.
232+
233+    Username and password are required. Other fields are optional.
234+    """
235+    username = models.CharField(_('username'), max_length=30, unique=True,
236+        help_text=_('Required. 30 characters or fewer. Letters, numbers and '
237+                    '@/./+/-/_ characters'))
238+    first_name = models.CharField(_('first name'), max_length=30, blank=True)
239+    last_name = models.CharField(_('last name'), max_length=30, blank=True)
240+    email = models.EmailField(_('e-mail address'), blank=True)
241+    password = models.CharField(_('password'), max_length=128)
242+    is_staff = models.BooleanField(_('staff status'), default=False,
243+        help_text=_('Designates whether the user can log into this admin '
244+                    'site.'))
245+    is_active = models.BooleanField(_('active'), default=True,
246+        help_text=_('Designates whether this user should be treated as '
247+                    'active. Unselect this instead of deleting accounts.'))
248+    is_superuser = models.BooleanField(_('superuser status'), default=False,
249+        help_text=_('Designates that this user has all permissions without '
250+                    'explicitly assigning them.'))
251+    last_login = models.DateTimeField(_('last login'), default=timezone.now)
252+    date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
253+    groups = models.ManyToManyField(Group, verbose_name=_('groups'),
254+        blank=True, help_text=_('The groups this user belongs to. A user will '
255+                                'get all permissions granted to each of '
256+                                'his/her group.'))
257+    user_permissions = models.ManyToManyField(Permission,
258+        verbose_name=_('user permissions'), blank=True,
259+        help_text='Specific permissions for this user.')
260+    objects = UserManager()
261+
262+    class Meta:
263+        abstract = True
264+
265+    def __unicode__(self):
266+        return self.username
267+
268+    def get_absolute_url(self):
269+        return "/users/%s/" % urllib.quote(smart_str(self.username))
270+
271+    def is_anonymous(self):
272+        """
273+        Always returns False. This is a way of comparing User objects to
274+        anonymous users.
275+        """
276+        return False
277+
278+    def is_authenticated(self):
279+        """
280+        Always return True. This is a way to tell if the user has been
281+        authenticated in templates.
282+        """
283+        return True
284+
285+    def get_full_name(self):
286+        """
287+        Returns the first_name plus the last_name, with a space in between.
288+        """
289+        full_name = u'%s %s' % (self.first_name, self.last_name)
290+        return full_name.strip()
291+
292+    def set_password(self, raw_password):
293+        self.password = make_password(raw_password)
294+
295+    def check_password(self, raw_password):
296+        """
297+        Returns a boolean of whether the raw_password was correct. Handles
298+        hashing formats behind the scenes.
299+        """
300+        def setter(raw_password):
301+            self.set_password(raw_password)
302+            self.save()
303+        return check_password(raw_password, self.password, setter)
304+
305+    def set_unusable_password(self):
306+        # Sets a value that will never be a valid hash
307+        self.password = make_password(None)
308+
309+    def has_usable_password(self):
310+        return is_password_usable(self.password)
311+
312+    def get_group_permissions(self, obj=None):
313+        """
314+        Returns a list of permission strings that this user has through his/her
315+        groups. This method queries all available auth backends. If an object
316+        is passed in, only permissions matching this object are returned.
317+        """
318+        permissions = set()
319+        for backend in auth.get_backends():
320+            if hasattr(backend, "get_group_permissions"):
321+                if obj is not None:
322+                    permissions.update(backend.get_group_permissions(self,
323+                                                                     obj))
324+                else:
325+                    permissions.update(backend.get_group_permissions(self))
326+        return permissions
327+
328+    def get_all_permissions(self, obj=None):
329+        return _user_get_all_permissions(self, obj)
330+
331+    def has_perm(self, perm, obj=None):
332+        """
333+        Returns True if the user has the specified permission. This method
334+        queries all available auth backends, but returns immediately if any
335+        backend returns True. Thus, a user who has permission from a single
336+        auth backend is assumed to have permission in general. If an object is
337+        provided, permissions for this specific object are checked.
338+        """
339+
340+        # Active superusers have all permissions.
341+        if self.is_active and self.is_superuser:
342+            return True
343+
344+        # Otherwise we need to check the backends.
345+        return _user_has_perm(self, perm, obj)
346+
347+    def has_perms(self, perm_list, obj=None):
348+        """
349+        Returns True if the user has each of the specified permissions. If
350+        object is passed, it checks if the user has all required perms for this
351+        object.
352+        """
353+        for perm in perm_list:
354+            if not self.has_perm(perm, obj):
355+                return False
356+        return True
357+
358+    def has_module_perms(self, app_label):
359+        """
360+        Returns True if the user has any permissions in the given app label.
361+        Uses pretty much the same logic as has_perm, above.
362+        """
363+        # Active superusers have all permissions.
364+        if self.is_active and self.is_superuser:
365+            return True
366+
367+        return _user_has_module_perms(self, app_label)
368+
369+    def email_user(self, subject, message, from_email=None):
370+        """
371+        Sends an email to this User.
372+        """
373+        send_mail(subject, message, from_email, [self.email])
374+
375+    def get_profile(self):
376+        """
377+        Returns site-specific profile for this user. Raises
378+        SiteProfileNotAvailable if this site does not allow profiles.
379+        """
380+        if not hasattr(self, '_profile_cache'):
381+            from django.conf import settings
382+            if not getattr(settings, 'AUTH_PROFILE_MODULE', False):
383+                raise SiteProfileNotAvailable(
384+                    'You need to set AUTH_PROFILE_MODULE in your project '
385+                    'settings')
386+            try:
387+                app_label, model_name = settings.AUTH_PROFILE_MODULE.split('.')
388+            except ValueError:
389+                raise SiteProfileNotAvailable(
390+                    'app_label and model_name should be separated by a dot in '
391+                    'the AUTH_PROFILE_MODULE setting')
392+            try:
393+                model = models.get_model(app_label, model_name)
394+                if model is None:
395+                    raise SiteProfileNotAvailable(
396+                        'Unable to load the profile model, check '
397+                        'AUTH_PROFILE_MODULE in your project settings')
398+                self._profile_cache = model._default_manager.using(
399+                                   self._state.db).get(user__id__exact=self.id)
400+                self._profile_cache.user = self
401+            except (ImportError, ImproperlyConfigured):
402+                raise SiteProfileNotAvailable
403+        return self._profile_cache
404+
405+
406+class AnonymousUser(object):
407+    id = None
408+    username = ''
409+    is_staff = False
410+    is_active = False
411+    is_superuser = False
412+    _groups = EmptyManager()
413+    _user_permissions = EmptyManager()
414+
415+    def __init__(self):
416+        pass
417+
418+    def __unicode__(self):
419+        return 'AnonymousUser'
420+
421+    def __str__(self):
422+        return unicode(self).encode('utf-8')
423+
424+    def __eq__(self, other):
425+        return isinstance(other, self.__class__)
426+
427+    def __ne__(self, other):
428+        return not self.__eq__(other)
429+
430+    def __hash__(self):
431+        return 1 # instances always return the same hash value
432+
433+    def save(self):
434+        raise NotImplementedError
435+
436+    def delete(self):
437+        raise NotImplementedError
438+
439+    def set_password(self, raw_password):
440+        raise NotImplementedError
441+
442+    def check_password(self, raw_password):
443+        raise NotImplementedError
444+
445+    def _get_groups(self):
446+        return self._groups
447+    groups = property(_get_groups)
448+
449+    def _get_user_permissions(self):
450+        return self._user_permissions
451+    user_permissions = property(_get_user_permissions)
452+
453+    def get_group_permissions(self, obj=None):
454+        return set()
455+
456+    def get_all_permissions(self, obj=None):
457+        return _user_get_all_permissions(self, obj=obj)
458+
459+    def has_perm(self, perm, obj=None):
460+        return _user_has_perm(self, perm, obj=obj)
461+
462+    def has_perms(self, perm_list, obj=None):
463+        for perm in perm_list:
464+            if not self.has_perm(perm, obj):
465+                return False
466+        return True
467+
468+    def has_module_perms(self, module):
469+        return _user_has_module_perms(self, module)
470+
471+    def is_anonymous(self):
472+        return True
473+
474+    def is_authenticated(self):
475+        return False
476diff --git a/django/contrib/auth/models.py b/django/contrib/auth/models.py
477index 4bb8cad..6291350 100644
478--- django/contrib/auth/models.py
479+++ django/contrib/auth/models.py
480@@ -1,450 +1,49 @@
481-import urllib
482-
483-from django.core.exceptions import ImproperlyConfigured
484-from django.core.mail import send_mail
485-from django.db import models
486-from django.db.models.manager import EmptyManager
487-from django.utils.crypto import get_random_string
488-from django.utils.encoding import smart_str
489+from django.conf import settings
490 from django.utils.translation import ugettext_lazy as _
491-from django.utils import timezone
492-
493-from django.contrib import auth
494-# UNUSABLE_PASSWORD is still imported here for backwards compatibility
495-from django.contrib.auth.hashers import (
496-    check_password, make_password, is_password_usable, UNUSABLE_PASSWORD)
497-from django.contrib.auth.signals import user_logged_in
498-from django.contrib.contenttypes.models import ContentType
499-
500+from django.core.exceptions import ImproperlyConfigured
501 
502-def update_last_login(sender, user, **kwargs):
503-    """
504-    A signal receiver which updates the last_login date for
505-    the user logging in.
506-    """
507-    user.last_login = timezone.now()
508-    user.save()
509-user_logged_in.connect(update_last_login)
510+from django.contrib.auth.base import *
511 
512 
513-class SiteProfileNotAvailable(Exception):
514+class AuthNotAvailable(Exception):
515     pass
516 
517 
518-class PermissionManager(models.Manager):
519-    def get_by_natural_key(self, codename, app_label, model):
520-        return self.get(
521-            codename=codename,
522-            content_type=ContentType.objects.get_by_natural_key(app_label,
523-                                                                model),
524-        )
525-
526-
527-class Permission(models.Model):
528-    """
529-    The permissions system provides a way to assign permissions to specific
530-    users and groups of users.
531-
532-    The permission system is used by the Django admin site, but may also be
533-    useful in your own code. The Django admin site uses permissions as follows:
534-
535-        - The "add" permission limits the user's ability to view the "add" form
536-          and add an object.
537-        - The "change" permission limits a user's ability to view the change
538-          list, view the "change" form and change an object.
539-        - The "delete" permission limits the ability to delete an object.
540-
541-    Permissions are set globally per type of object, not per specific object
542-    instance. It is possible to say "Mary may change news stories," but it's
543-    not currently possible to say "Mary may change news stories, but only the
544-    ones she created herself" or "Mary may only change news stories that have a
545-    certain status or publication date."
546-
547-    Three basic permissions -- add, change and delete -- are automatically
548-    created for each Django model.
549-    """
550-    name = models.CharField(_('name'), max_length=50)
551-    content_type = models.ForeignKey(ContentType)
552-    codename = models.CharField(_('codename'), max_length=100)
553-    objects = PermissionManager()
554-
555-    class Meta:
556-        verbose_name = _('permission')
557-        verbose_name_plural = _('permissions')
558-        unique_together = (('content_type', 'codename'),)
559-        ordering = ('content_type__app_label', 'content_type__model',
560-                    'codename')
561-
562-    def __unicode__(self):
563-        return u"%s | %s | %s" % (
564-            unicode(self.content_type.app_label),
565-            unicode(self.content_type),
566-            unicode(self.name))
567-
568-    def natural_key(self):
569-        return (self.codename,) + self.content_type.natural_key()
570-    natural_key.dependencies = ['contenttypes.contenttype']
571-
572-
573-class Group(models.Model):
574-    """
575-    Groups are a generic way of categorizing users to apply permissions, or
576-    some other label, to those users. A user can belong to any number of
577-    groups.
578-
579-    A user in a group automatically has all the permissions granted to that
580-    group. For example, if the group Site editors has the permission
581-    can_edit_home_page, any user in that group will have that permission.
582-
583-    Beyond permissions, groups are a convenient way to categorize users to
584-    apply some label, or extended functionality, to them. For example, you
585-    could create a group 'Special users', and you could write code that would
586-    do special things to those users -- such as giving them access to a
587-    members-only portion of your site, or sending them members-only email
588-    messages.
589-    """
590-    name = models.CharField(_('name'), max_length=80, unique=True)
591-    permissions = models.ManyToManyField(Permission,
592-        verbose_name=_('permissions'), blank=True)
593-
594-    class Meta:
595-        verbose_name = _('group')
596-        verbose_name_plural = _('groups')
597-
598-    def __unicode__(self):
599-        return self.name
600-
601-
602-class UserManager(models.Manager):
603-    def create_user(self, username, email=None, password=None):
604-        """
605-        Creates and saves a User with the given username, email and password.
606-        """
607-        now = timezone.now()
608-
609-        # Normalize the address by lowercasing the domain part of the email
610-        # address.
611-        email = email or ''
612-        try:
613-            email_name, domain_part = email.strip().split('@', 1)
614-        except ValueError:
615-            pass
616-        else:
617-            email = '@'.join([email_name, domain_part.lower()])
618-
619-        user = self.model(username=username, email=email, is_staff=False,
620-                         is_active=True, is_superuser=False, last_login=now,
621-                         date_joined=now)
622-
623-        user.set_password(password)
624-        user.save(using=self._db)
625-        return user
626-
627-    def create_superuser(self, username, email, password):
628-        u = self.create_user(username, email, password)
629-        u.is_staff = True
630-        u.is_active = True
631-        u.is_superuser = True
632-        u.save(using=self._db)
633-        return u
634-
635-    def make_random_password(self, length=10,
636-                             allowed_chars='abcdefghjkmnpqrstuvwxyz'
637-                                           'ABCDEFGHJKLMNPQRSTUVWXYZ'
638-                                           '23456789'):
639-        """
640-        Generates a random password with the given length and given
641-        allowed_chars. Note that the default value of allowed_chars does not
642-        have "I" or "O" or letters and digits that look similar -- just to
643-        avoid confusion.
644-        """
645-        return get_random_string(length, allowed_chars)
646-
647-
648-# A few helper functions for common logic between User and AnonymousUser.
649-def _user_get_all_permissions(user, obj):
650-    permissions = set()
651-    for backend in auth.get_backends():
652-        if hasattr(backend, "get_all_permissions"):
653-            if obj is not None:
654-                permissions.update(backend.get_all_permissions(user, obj))
655-            else:
656-                permissions.update(backend.get_all_permissions(user))
657-    return permissions
658-
659-
660-def _user_has_perm(user, perm, obj):
661-    anon = user.is_anonymous()
662-    active = user.is_active
663-    for backend in auth.get_backends():
664-        if anon or active or backend.supports_inactive_user:
665-            if hasattr(backend, "has_perm"):
666-                if obj is not None:
667-                    if backend.has_perm(user, perm, obj):
668-                            return True
669-                else:
670-                    if backend.has_perm(user, perm):
671-                        return True
672-    return False
673-
674-
675-def _user_has_module_perms(user, app_label):
676-    anon = user.is_anonymous()
677-    active = user.is_active
678-    for backend in auth.get_backends():
679-        if anon or active or backend.supports_inactive_user:
680-            if hasattr(backend, "has_module_perms"):
681-                if backend.has_module_perms(user, app_label):
682-                    return True
683-    return False
684-
685-
686-class User(models.Model):
687-    """
688-    Users within the Django authentication system are represented by this
689-    model.
690-
691-    Username and password are required. Other fields are optional.
692-    """
693-    username = models.CharField(_('username'), max_length=30, unique=True,
694-        help_text=_('Required. 30 characters or fewer. Letters, numbers and '
695-                    '@/./+/-/_ characters'))
696-    first_name = models.CharField(_('first name'), max_length=60, blank=True)
697-    last_name = models.CharField(_('last name'), max_length=60, blank=True)
698-    email = models.EmailField(_('e-mail address'), max_length=255, blank=True)
699-    password = models.CharField(_('password'), max_length=128)
700-    is_staff = models.BooleanField(_('staff status'), default=False,
701-        help_text=_('Designates whether the user can log into this admin '
702-                    'site.'))
703-    is_active = models.BooleanField(_('active'), default=True,
704-        help_text=_('Designates whether this user should be treated as '
705-                    'active. Unselect this instead of deleting accounts.'))
706-    is_superuser = models.BooleanField(_('superuser status'), default=False,
707-        help_text=_('Designates that this user has all permissions without '
708-                    'explicitly assigning them.'))
709-    last_login = models.DateTimeField(_('last login'), default=timezone.now)
710-    date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
711-    groups = models.ManyToManyField(Group, verbose_name=_('groups'),
712-        blank=True, help_text=_('The groups this user belongs to. A user will '
713-                                'get all permissions granted to each of '
714-                                'his/her group.'))
715-    user_permissions = models.ManyToManyField(Permission,
716-        verbose_name=_('user permissions'), blank=True,
717-        help_text='Specific permissions for this user.')
718-    objects = UserManager()
719-
720-    class Meta:
721-        verbose_name = _('user')
722-        verbose_name_plural = _('users')
723-
724-    def __unicode__(self):
725-        return self.username
726-
727-    def get_absolute_url(self):
728-        return "/users/%s/" % urllib.quote(smart_str(self.username))
729-
730-    def is_anonymous(self):
731-        """
732-        Always returns False. This is a way of comparing User objects to
733-        anonymous users.
734-        """
735-        return False
736-
737-    def is_authenticated(self):
738-        """
739-        Always return True. This is a way to tell if the user has been
740-        authenticated in templates.
741-        """
742-        return True
743-
744-    def get_full_name(self):
745-        """
746-        Returns the first_name plus the last_name, with a space in between.
747-        """
748-        full_name = u'%s %s' % (self.first_name, self.last_name)
749-        return full_name.strip()
750-
751-    def set_password(self, raw_password):
752-        self.password = make_password(raw_password)
753-
754-    def check_password(self, raw_password):
755-        """
756-        Returns a boolean of whether the raw_password was correct. Handles
757-        hashing formats behind the scenes.
758-        """
759-        def setter(raw_password):
760-            self.set_password(raw_password)
761-            self.save()
762-        return check_password(raw_password, self.password, setter)
763-
764-    def set_unusable_password(self):
765-        # Sets a value that will never be a valid hash
766-        self.password = make_password(None)
767-
768-    def has_usable_password(self):
769-        return is_password_usable(self.password)
770-
771-    def get_group_permissions(self, obj=None):
772-        """
773-        Returns a list of permission strings that this user has through his/her
774-        groups. This method queries all available auth backends. If an object
775-        is passed in, only permissions matching this object are returned.
776-        """
777-        permissions = set()
778-        for backend in auth.get_backends():
779-            if hasattr(backend, "get_group_permissions"):
780-                if obj is not None:
781-                    permissions.update(backend.get_group_permissions(self,
782-                                                                     obj))
783-                else:
784-                    permissions.update(backend.get_group_permissions(self))
785-        return permissions
786-
787-    def get_all_permissions(self, obj=None):
788-        return _user_get_all_permissions(self, obj)
789-
790-    def has_perm(self, perm, obj=None):
791-        """
792-        Returns True if the user has the specified permission. This method
793-        queries all available auth backends, but returns immediately if any
794-        backend returns True. Thus, a user who has permission from a single
795-        auth backend is assumed to have permission in general. If an object is
796-        provided, permissions for this specific object are checked.
797-        """
798-
799-        # Active superusers have all permissions.
800-        if self.is_active and self.is_superuser:
801-            return True
802-
803-        # Otherwise we need to check the backends.
804-        return _user_has_perm(self, perm, obj)
805-
806-    def has_perms(self, perm_list, obj=None):
807-        """
808-        Returns True if the user has each of the specified permissions. If
809-        object is passed, it checks if the user has all required perms for this
810-        object.
811-        """
812-        for perm in perm_list:
813-            if not self.has_perm(perm, obj):
814-                return False
815-        return True
816-
817-    def has_module_perms(self, app_label):
818-        """
819-        Returns True if the user has any permissions in the given app label.
820-        Uses pretty much the same logic as has_perm, above.
821-        """
822-        # Active superusers have all permissions.
823-        if self.is_active and self.is_superuser:
824-            return True
825-
826-        return _user_has_module_perms(self, app_label)
827-
828-    def email_user(self, subject, message, from_email=None):
829-        """
830-        Sends an email to this User.
831-        """
832-        send_mail(subject, message, from_email, [self.email])
833-
834-    def get_profile(self):
835-        """
836-        Returns site-specific profile for this user. Raises
837-        SiteProfileNotAvailable if this site does not allow profiles.
838-        """
839-        if not hasattr(self, '_profile_cache'):
840-            from django.conf import settings
841-            if not getattr(settings, 'AUTH_PROFILE_MODULE', False):
842-                raise SiteProfileNotAvailable(
843-                    'You need to set AUTH_PROFILE_MODULE in your project '
844-                    'settings')
845-            try:
846-                app_label, model_name = settings.AUTH_PROFILE_MODULE.split('.')
847-            except ValueError:
848-                raise SiteProfileNotAvailable(
849-                    'app_label and model_name should be separated by a dot in '
850-                    'the AUTH_PROFILE_MODULE setting')
851-            try:
852-                model = models.get_model(app_label, model_name)
853-                if model is None:
854-                    raise SiteProfileNotAvailable(
855-                        'Unable to load the profile model, check '
856-                        'AUTH_PROFILE_MODULE in your project settings')
857-                self._profile_cache = model._default_manager.using(
858-                                   self._state.db).get(user__id__exact=self.id)
859-                self._profile_cache.user = self
860-            except (ImportError, ImproperlyConfigured):
861-                raise SiteProfileNotAvailable
862-        return self._profile_cache
863-
864-
865-class AnonymousUser(object):
866-    id = None
867-    username = ''
868-    is_staff = False
869-    is_active = False
870-    is_superuser = False
871-    _groups = EmptyManager()
872-    _user_permissions = EmptyManager()
873-
874-    def __init__(self):
875-        pass
876-
877-    def __unicode__(self):
878-        return 'AnonymousUser'
879-
880-    def __str__(self):
881-        return unicode(self).encode('utf-8')
882-
883-    def __eq__(self, other):
884-        return isinstance(other, self.__class__)
885-
886-    def __ne__(self, other):
887-        return not self.__eq__(other)
888-
889-    def __hash__(self):
890-        return 1 # instances always return the same hash value
891-
892-    def save(self):
893-        raise NotImplementedError
894-
895-    def delete(self):
896-        raise NotImplementedError
897-
898-    def set_password(self, raw_password):
899-        raise NotImplementedError
900-
901-    def check_password(self, raw_password):
902-        raise NotImplementedError
903-
904-    def _get_groups(self):
905-        return self._groups
906-    groups = property(_get_groups)
907-
908-    def _get_user_permissions(self):
909-        return self._user_permissions
910-    user_permissions = property(_get_user_permissions)
911-
912-    def get_group_permissions(self, obj=None):
913-        return set()
914-
915-    def get_all_permissions(self, obj=None):
916-        return _user_get_all_permissions(self, obj=obj)
917-
918-    def has_perm(self, perm, obj=None):
919-        return _user_has_perm(self, perm, obj=obj)
920-
921-    def has_perms(self, perm_list, obj=None):
922-        for perm in perm_list:
923-            if not self.has_perm(perm, obj):
924-                return False
925-        return True
926-
927-    def has_module_perms(self, module):
928-        return _user_has_module_perms(self, module)
929-
930-    def is_anonymous(self):
931-        return True
932-
933-    def is_authenticated(self):
934-        return False
935+if hasattr(settings, 'AUTH_USER_MODULE'):
936+    try:
937+        app_label, model_name = settings.AUTH_USER_MODULE.split('.')
938+    except ValueError:
939+        raise AuthNotAvailable('app_label and model_name should'
940+                ' be separated by a dot in the AUTH_USER_MODULE set'
941+                'ting')
942+
943+    try:
944+        # Grab the AUTH_USER_MODULE path and classname from the settings.
945+        module = __import__(app_label + '.models', {}, {}, [''])
946+        # Store the user model so it is accessible with the standard
947+        # 'from django.contrib.auth.models import User'
948+        User = getattr(module, model_name, None)
949+
950+        if User is None:
951+            raise AuthNotAvailable('Unable to load the user '
952+                'model, check AUTH_USER_MODULE in your project sett'
953+                'ings')
954+    except (ImportError, ImproperlyConfigured):
955+        raise AuthNotAvailable
956+
957+    # Add te User model to the django models cache
958+    # These two lines allow the custom auth_user model to play nicely with syncdb
959+    # and other systems that rely on functions like
960+    # django.db.models.loading.get_model(...)
961+    from django.db.models.loading import cache
962+    cache.register_models('auth', User)
963+
964+    # We need to remove whatever we used as the AUTH_USER_MODUlE from the
965+    # db cache so apps like contenttypes don't think that it's part
966+    # of contrib.auth
967+    del cache.app_models['auth'][User.__name__.lower()]
968+else:
969+    class User(UserTemplate):
970+        class Meta:
971+            verbose_name = _('user')
972+            verbose_name_plural = _('users')