Modified auth app so that login with alternate auth app is possible.

This commit is contained in:
Russell Keith-Magee 2012-06-04 20:41:37 +08:00
parent dabe362836
commit 507bb50a92
10 changed files with 71 additions and 39 deletions

View File

@ -9,6 +9,7 @@ from django.utils.translation import ugettext_lazy, ugettext as _
ERROR_MESSAGE = ugettext_lazy("Please enter the correct username and password "
"for a staff account. Note that both fields are case-sensitive.")
class AdminAuthenticationForm(AuthenticationForm):
"""
A custom authentication form used in the admin app.

View File

@ -2,7 +2,7 @@ from functools import update_wrapper
from django.http import Http404, HttpResponseRedirect
from django.contrib.admin import ModelAdmin, actions
from django.contrib.admin.forms import AdminAuthenticationForm
from django.contrib.auth import REDIRECT_FIELD_NAME
from django.contrib.auth import REDIRECT_FIELD_NAME, get_user_model
from django.contrib.contenttypes import views as contenttype_views
from django.views.decorators.csrf import csrf_protect
from django.db.models.base import ModelBase
@ -79,20 +79,23 @@ class AdminSite(object):
if model in self._registry:
raise AlreadyRegistered('The model %s is already registered' % model.__name__)
# If we got **options then dynamically construct a subclass of
# admin_class with those **options.
if options:
# For reasons I don't quite understand, without a __module__
# the created class appears to "live" in the wrong place,
# which causes issues later on.
options['__module__'] = __name__
admin_class = type("%sAdmin" % model.__name__, (admin_class,), options)
# Ignore the registration if the model has been
# swapped out.
if not model._meta.swapped:
# If we got **options then dynamically construct a subclass of
# admin_class with those **options.
if options:
# For reasons I don't quite understand, without a __module__
# the created class appears to "live" in the wrong place,
# which causes issues later on.
options['__module__'] = __name__
admin_class = type("%sAdmin" % model.__name__, (admin_class,), options)
# Validate (which might be a no-op)
validate(admin_class, model)
# Validate (which might be a no-op)
validate(admin_class, model)
# Instantiate the admin class to save in the registry
self._registry[model] = admin_class(model, self)
# Instantiate the admin class to save in the registry
self._registry[model] = admin_class(model, self)
def unregister(self, model_or_iterable):
"""
@ -317,6 +320,7 @@ class AdminSite(object):
REDIRECT_FIELD_NAME: request.get_full_path(),
}
context.update(extra_context or {})
defaults = {
'extra_context': context,
'current_app': self.name,

View File

@ -26,7 +26,7 @@
{% if user.is_active and user.is_staff %}
<div id="user-tools">
{% trans 'Welcome,' %}
<strong>{% filter force_escape %}{% firstof user.first_name user.username %}{% endfilter %}</strong>.
<strong>{% filter force_escape %}{% firstof user.get_short_name user.username %}{% endfilter %}</strong>.
{% block userlinks %}
{% url 'django-admindocs-docroot' as docsroot %}
{% if docsroot %}

View File

@ -6,9 +6,10 @@ SESSION_KEY = '_auth_user_id'
BACKEND_SESSION_KEY = '_auth_user_backend'
REDIRECT_FIELD_NAME = 'next'
def load_backend(path):
i = path.rfind('.')
module, attr = path[:i], path[i+1:]
module, attr = path[:i], path[i + 1:]
try:
mod = import_module(module)
except ImportError as e:
@ -21,6 +22,7 @@ def load_backend(path):
raise ImproperlyConfigured('Module "%s" does not define a "%s" authentication backend' % (module, attr))
return cls()
def get_backends():
from django.conf import settings
backends = []
@ -30,6 +32,7 @@ def get_backends():
raise ImproperlyConfigured('No authentication backends have been defined. Does AUTHENTICATION_BACKENDS contain anything?')
return backends
def authenticate(**credentials):
"""
If the given credentials are valid, return a User object.
@ -46,6 +49,7 @@ def authenticate(**credentials):
user.backend = "%s.%s" % (backend.__module__, backend.__class__.__name__)
return user
def login(request, user):
"""
Persist a user id and a backend in the request. This way a user doesn't
@ -69,6 +73,7 @@ def login(request, user):
request.user = user
user_logged_in.send(sender=user.__class__, request=request, user=user)
def logout(request):
"""
Removes the authenticated user's ID from the request and flushes their
@ -86,6 +91,16 @@ def logout(request):
from django.contrib.auth.models import AnonymousUser
request.user = AnonymousUser()
def get_user_model():
"Return the User model that is active in this project"
from django.conf import settings
from django.db.models import get_model
app_label, model_name = settings.AUTH_USER_MODEL.split('.')
return get_model(app_label, model_name)
def get_user(request):
from django.contrib.auth.models import AnonymousUser
try:

View File

@ -1,4 +1,5 @@
from django.contrib.auth.models import User, Permission
from django.contrib.auth import get_user_model
from django.contrib.auth.models import Permission
class ModelBackend(object):
@ -10,10 +11,13 @@ class ModelBackend(object):
# configurable.
def authenticate(self, username=None, password=None):
try:
user = User.objects.get(username=username)
UserModel = get_user_model()
user = UserModel.objects.get(**{
getattr(UserModel, 'USERNAME_FIELD', 'username'): username
})
if user.check_password(password):
return user
except User.DoesNotExist:
except UserModel.DoesNotExist:
return None
def get_group_permissions(self, user_obj, obj=None):
@ -58,8 +62,9 @@ class ModelBackend(object):
def get_user(self, user_id):
try:
return User.objects.get(pk=user_id)
except User.DoesNotExist:
UserModel = get_user_model()
return UserModel.objects.get(pk=user_id)
except UserModel.DoesNotExist:
return None
@ -92,17 +97,23 @@ class RemoteUserBackend(ModelBackend):
user = None
username = self.clean_username(remote_user)
UserModel = get_user_model()
# Note that this could be accomplished in one try-except clause, but
# instead we use get_or_create when creating unknown users since it has
# built-in safeguards for multiple threads.
if self.create_unknown_user:
user, created = User.objects.get_or_create(username=username)
user, created = UserModel.objects.get_or_create(**{
getattr(UserModel, 'USERNAME_FIELD', 'username'): username
})
if created:
user = self.configure_user(user)
else:
try:
user = User.objects.get(username=username)
except User.DoesNotExist:
user = UserModel.objects.get(**{
getattr(UserModel, 'USERNAME_FIELD', 'username'): username
})
except UserModel.DoesNotExist:
pass
return user

View File

@ -5,10 +5,9 @@ import getpass
import locale
import unicodedata
from django.contrib.auth import models as auth_app
from django.contrib.auth import models as auth_app, get_user_model
from django.core import exceptions
from django.db.models import get_models, signals
from django.contrib.auth.models import User, get_user_model
def _get_permission_codename(action, opts):
@ -106,7 +105,7 @@ def get_default_username(check_db=True):
"""
# If the User model has been swapped out, we can't make any assumptions
# about the default user name.
if User._meta.swapped:
if auth_app.User._meta.swapped:
return ''
default_username = get_system_username()
@ -118,15 +117,15 @@ def get_default_username(check_db=True):
# Run the username validator
try:
User._meta.get_field('username').run_validators(default_username)
auth_app.User._meta.get_field('username').run_validators(default_username)
except exceptions.ValidationError:
return ''
# Don't return the default username if it is already taken.
if check_db and default_username:
try:
User.objects.get(username=default_username)
except User.DoesNotExist:
auth_app.User.objects.get(username=default_username)
except auth_app.User.DoesNotExist:
pass
else:
return ''

View File

@ -1,8 +1,8 @@
import getpass
from optparse import make_option
from django.contrib.auth import get_user_model
from django.core.management.base import BaseCommand, CommandError
from django.contrib.auth.models import get_user_model
from django.db import DEFAULT_DB_ALIAS

View File

@ -6,8 +6,8 @@ import getpass
import sys
from optparse import make_option
from django.contrib.auth import get_user_model
from django.contrib.auth.management import get_default_username
from django.contrib.auth.models import get_user_model
from django.core import exceptions
from django.core.management.base import BaseCommand, CommandError
from django.db import DEFAULT_DB_ALIAS

View File

@ -1,7 +1,6 @@
import re
import urllib
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.core.mail import send_mail
from django.core import validators
@ -271,12 +270,6 @@ class AbstractBaseUser(models.Model):
raise NotImplementedError()
def get_user_model():
"Return the User model that is active in this project"
app_label, model_name = settings.AUTH_USER_MODEL.split('.')
return models.get_model(app_label, model_name)
class User(AbstractBaseUser):
"""
Users within the Django authentication system are represented by this

View File

@ -70,6 +70,7 @@ def login(request, template_name='registration/login.html',
return TemplateResponse(request, template_name, context,
current_app=current_app)
def logout(request, next_page=None,
template_name='registration/logged_out.html',
redirect_field_name=REDIRECT_FIELD_NAME,
@ -100,6 +101,7 @@ def logout(request, next_page=None,
# Redirect to this page until the session has been cleared.
return HttpResponseRedirect(next_page or request.path)
def logout_then_login(request, login_url=None, current_app=None, extra_context=None):
"""
Logs out the user if he is logged in. Then redirects to the log-in page.
@ -108,6 +110,7 @@ def logout_then_login(request, login_url=None, current_app=None, extra_context=N
login_url = settings.LOGIN_URL
return logout(request, login_url, current_app=current_app, extra_context=extra_context)
def redirect_to_login(next, login_url=None,
redirect_field_name=REDIRECT_FIELD_NAME):
"""
@ -124,6 +127,7 @@ def redirect_to_login(next, login_url=None,
return HttpResponseRedirect(urlparse.urlunparse(login_url_parts))
# 4 views for password reset:
# - password_reset sends the mail
# - password_reset_done shows a success message for the above
@ -169,6 +173,7 @@ def password_reset(request, is_admin_site=False,
return TemplateResponse(request, template_name, context,
current_app=current_app)
def password_reset_done(request,
template_name='registration/password_reset_done.html',
current_app=None, extra_context=None):
@ -178,6 +183,7 @@ def password_reset_done(request,
return TemplateResponse(request, template_name, context,
current_app=current_app)
# Doesn't need csrf_protect since no-one can guess the URL
@sensitive_post_parameters()
@never_cache
@ -191,7 +197,7 @@ def password_reset_confirm(request, uidb36=None, token=None,
View that checks the hash in a password reset link and presents a
form for entering a new password.
"""
assert uidb36 is not None and token is not None # checked by URLconf
assert uidb36 is not None and token is not None # checked by URLconf
if post_reset_redirect is None:
post_reset_redirect = reverse('django.contrib.auth.views.password_reset_complete')
try:
@ -221,6 +227,7 @@ def password_reset_confirm(request, uidb36=None, token=None,
return TemplateResponse(request, template_name, context,
current_app=current_app)
def password_reset_complete(request,
template_name='registration/password_reset_complete.html',
current_app=None, extra_context=None):
@ -232,6 +239,7 @@ def password_reset_complete(request,
return TemplateResponse(request, template_name, context,
current_app=current_app)
@sensitive_post_parameters()
@csrf_protect
@login_required
@ -257,6 +265,7 @@ def password_change(request,
return TemplateResponse(request, template_name, context,
current_app=current_app)
@login_required
def password_change_done(request,
template_name='registration/password_change_done.html',