Fixed #8342 -- Removed code from the admin that assumed that you can't login with an email address (nixed by r12634). Also refactored login code slightly to be DRY by using more of auth app's forms and views.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@14769 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
07705ca129
commit
cc64fb5c4b
|
@ -0,0 +1,43 @@
|
||||||
|
from django import forms
|
||||||
|
|
||||||
|
from django.contrib.auth import authenticate
|
||||||
|
from django.contrib.auth.forms import AuthenticationForm
|
||||||
|
from django.contrib.auth.models import User
|
||||||
|
|
||||||
|
from django.utils.translation import ugettext_lazy, ugettext as _
|
||||||
|
|
||||||
|
ERROR_MESSAGE = ugettext_lazy("Please enter a correct username and password. "
|
||||||
|
"Note that both fields are case-sensitive.")
|
||||||
|
|
||||||
|
class AdminAuthenticationForm(AuthenticationForm):
|
||||||
|
"""
|
||||||
|
A custom authentication form used in the admin app.
|
||||||
|
|
||||||
|
"""
|
||||||
|
this_is_the_login_form = forms.BooleanField(widget=forms.HiddenInput, initial=1,
|
||||||
|
error_messages={'required': ugettext_lazy("Please log in again, because your session has expired.")})
|
||||||
|
|
||||||
|
def clean(self):
|
||||||
|
username = self.cleaned_data.get('username')
|
||||||
|
password = self.cleaned_data.get('password')
|
||||||
|
message = ERROR_MESSAGE
|
||||||
|
|
||||||
|
if username and password:
|
||||||
|
self.user_cache = authenticate(username=username, password=password)
|
||||||
|
if self.user_cache is None:
|
||||||
|
if username is not None and u'@' in username:
|
||||||
|
# Mistakenly entered e-mail address instead of username? Look it up.
|
||||||
|
try:
|
||||||
|
user = User.objects.get(email=username)
|
||||||
|
except (User.DoesNotExist, User.MultipleObjectsReturned):
|
||||||
|
# Nothing to do here, moving along.
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
if user.check_password(password):
|
||||||
|
message = _("Your e-mail address is not your username."
|
||||||
|
" Try '%s' instead.") % user.username
|
||||||
|
raise forms.ValidationError(message)
|
||||||
|
elif not self.user_cache.is_active or not self.user_cache.is_staff:
|
||||||
|
raise forms.ValidationError(message)
|
||||||
|
self.check_for_test_cookie()
|
||||||
|
return self.cleaned_data
|
|
@ -1,8 +1,8 @@
|
||||||
import re
|
import re
|
||||||
from django import http, template
|
from django import http, template
|
||||||
from django.contrib.admin import ModelAdmin
|
from django.contrib.admin import ModelAdmin, actions
|
||||||
from django.contrib.admin import actions
|
from django.contrib.admin.forms import AdminAuthenticationForm, ERROR_MESSAGE
|
||||||
from django.contrib.auth import authenticate, login
|
from django.contrib.auth import REDIRECT_FIELD_NAME, authenticate, login
|
||||||
from django.views.decorators.csrf import csrf_protect
|
from django.views.decorators.csrf import csrf_protect
|
||||||
from django.db.models.base import ModelBase
|
from django.db.models.base import ModelBase
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
|
@ -15,7 +15,6 @@ from django.utils.translation import ugettext_lazy, ugettext as _
|
||||||
from django.views.decorators.cache import never_cache
|
from django.views.decorators.cache import never_cache
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
ERROR_MESSAGE = ugettext_lazy("Please enter a correct username and password. Note that both fields are case-sensitive.")
|
|
||||||
LOGIN_FORM_KEY = 'this_is_the_login_form'
|
LOGIN_FORM_KEY = 'this_is_the_login_form'
|
||||||
|
|
||||||
class AlreadyRegistered(Exception):
|
class AlreadyRegistered(Exception):
|
||||||
|
@ -32,7 +31,7 @@ class AdminSite(object):
|
||||||
functions that present a full admin interface for the collection of registered
|
functions that present a full admin interface for the collection of registered
|
||||||
models.
|
models.
|
||||||
"""
|
"""
|
||||||
|
login_form = None
|
||||||
index_template = None
|
index_template = None
|
||||||
app_index_template = None
|
app_index_template = None
|
||||||
login_template = None
|
login_template = None
|
||||||
|
@ -127,12 +126,12 @@ class AdminSite(object):
|
||||||
"""
|
"""
|
||||||
return self._global_actions[name]
|
return self._global_actions[name]
|
||||||
|
|
||||||
|
@property
|
||||||
def actions(self):
|
def actions(self):
|
||||||
"""
|
"""
|
||||||
Get all the enabled actions as an iterable of (name, func).
|
Get all the enabled actions as an iterable of (name, func).
|
||||||
"""
|
"""
|
||||||
return self._actions.iteritems()
|
return self._actions.iteritems()
|
||||||
actions = property(actions)
|
|
||||||
|
|
||||||
def has_permission(self, request):
|
def has_permission(self, request):
|
||||||
"""
|
"""
|
||||||
|
@ -240,9 +239,9 @@ class AdminSite(object):
|
||||||
)
|
)
|
||||||
return urlpatterns
|
return urlpatterns
|
||||||
|
|
||||||
|
@property
|
||||||
def urls(self):
|
def urls(self):
|
||||||
return self.get_urls(), self.app_name, self.name
|
return self.get_urls(), self.app_name, self.name
|
||||||
urls = property(urls)
|
|
||||||
|
|
||||||
def password_change(self, request):
|
def password_change(self, request):
|
||||||
"""
|
"""
|
||||||
|
@ -254,18 +253,22 @@ class AdminSite(object):
|
||||||
else:
|
else:
|
||||||
url = reverse('admin:password_change_done', current_app=self.name)
|
url = reverse('admin:password_change_done', current_app=self.name)
|
||||||
defaults = {
|
defaults = {
|
||||||
|
'current_app': self.name,
|
||||||
'post_change_redirect': url
|
'post_change_redirect': url
|
||||||
}
|
}
|
||||||
if self.password_change_template is not None:
|
if self.password_change_template is not None:
|
||||||
defaults['template_name'] = self.password_change_template
|
defaults['template_name'] = self.password_change_template
|
||||||
return password_change(request, **defaults)
|
return password_change(request, **defaults)
|
||||||
|
|
||||||
def password_change_done(self, request):
|
def password_change_done(self, request, extra_context=None):
|
||||||
"""
|
"""
|
||||||
Displays the "success" page after a password change.
|
Displays the "success" page after a password change.
|
||||||
"""
|
"""
|
||||||
from django.contrib.auth.views import password_change_done
|
from django.contrib.auth.views import password_change_done
|
||||||
defaults = {}
|
defaults = {
|
||||||
|
'current_app': self.name,
|
||||||
|
'extra_context': extra_context or {},
|
||||||
|
}
|
||||||
if self.password_change_done_template is not None:
|
if self.password_change_done_template is not None:
|
||||||
defaults['template_name'] = self.password_change_done_template
|
defaults['template_name'] = self.password_change_done_template
|
||||||
return password_change_done(request, **defaults)
|
return password_change_done(request, **defaults)
|
||||||
|
@ -283,69 +286,44 @@ class AdminSite(object):
|
||||||
from django.views.i18n import null_javascript_catalog as javascript_catalog
|
from django.views.i18n import null_javascript_catalog as javascript_catalog
|
||||||
return javascript_catalog(request, packages='django.conf')
|
return javascript_catalog(request, packages='django.conf')
|
||||||
|
|
||||||
def logout(self, request):
|
@never_cache
|
||||||
|
def logout(self, request, extra_context=None):
|
||||||
"""
|
"""
|
||||||
Logs out the user for the given HttpRequest.
|
Logs out the user for the given HttpRequest.
|
||||||
|
|
||||||
This should *not* assume the user is already logged in.
|
This should *not* assume the user is already logged in.
|
||||||
"""
|
"""
|
||||||
from django.contrib.auth.views import logout
|
from django.contrib.auth.views import logout
|
||||||
defaults = {}
|
defaults = {
|
||||||
|
'current_app': self.name,
|
||||||
|
'extra_context': extra_context or {},
|
||||||
|
}
|
||||||
if self.logout_template is not None:
|
if self.logout_template is not None:
|
||||||
defaults['template_name'] = self.logout_template
|
defaults['template_name'] = self.logout_template
|
||||||
return logout(request, **defaults)
|
return logout(request, **defaults)
|
||||||
logout = never_cache(logout)
|
|
||||||
|
|
||||||
def login(self, request):
|
@never_cache
|
||||||
|
def login(self, request, extra_context=None):
|
||||||
"""
|
"""
|
||||||
Displays the login form for the given HttpRequest.
|
Displays the login form for the given HttpRequest.
|
||||||
"""
|
"""
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.views import login
|
||||||
|
context = {
|
||||||
# If this isn't already the login page, display it.
|
'title': _('Log in'),
|
||||||
if LOGIN_FORM_KEY not in request.POST:
|
'root_path': self.root_path,
|
||||||
if request.POST:
|
'app_path': request.get_full_path(),
|
||||||
message = _("Please log in again, because your session has expired.")
|
REDIRECT_FIELD_NAME: request.get_full_path(),
|
||||||
else:
|
}
|
||||||
message = ""
|
context.update(extra_context or {})
|
||||||
return self.display_login_form(request, message)
|
defaults = {
|
||||||
|
'extra_context': context,
|
||||||
# Check that the user accepts cookies.
|
'current_app': self.name,
|
||||||
if not request.session.test_cookie_worked():
|
'authentication_form': self.login_form or AdminAuthenticationForm,
|
||||||
message = _("Looks like your browser isn't configured to accept cookies. Please enable cookies, reload this page, and try again.")
|
'template_name': self.login_template or 'admin/login.html',
|
||||||
return self.display_login_form(request, message)
|
}
|
||||||
else:
|
return login(request, **defaults)
|
||||||
request.session.delete_test_cookie()
|
|
||||||
|
|
||||||
# Check the password.
|
|
||||||
username = request.POST.get('username', None)
|
|
||||||
password = request.POST.get('password', None)
|
|
||||||
user = authenticate(username=username, password=password)
|
|
||||||
if user is None:
|
|
||||||
message = ERROR_MESSAGE
|
|
||||||
if username is not None and u'@' in username:
|
|
||||||
# Mistakenly entered e-mail address instead of username? Look it up.
|
|
||||||
try:
|
|
||||||
user = User.objects.get(email=username)
|
|
||||||
except (User.DoesNotExist, User.MultipleObjectsReturned):
|
|
||||||
message = _("Usernames cannot contain the '@' character.")
|
|
||||||
else:
|
|
||||||
if user.check_password(password):
|
|
||||||
message = _("Your e-mail address is not your username."
|
|
||||||
" Try '%s' instead.") % user.username
|
|
||||||
else:
|
|
||||||
message = _("Usernames cannot contain the '@' character.")
|
|
||||||
return self.display_login_form(request, message)
|
|
||||||
|
|
||||||
# The user data is correct; log in the user in and continue.
|
|
||||||
else:
|
|
||||||
if user.is_active and user.is_staff:
|
|
||||||
login(request, user)
|
|
||||||
return http.HttpResponseRedirect(request.get_full_path())
|
|
||||||
else:
|
|
||||||
return self.display_login_form(request, ERROR_MESSAGE)
|
|
||||||
login = never_cache(login)
|
|
||||||
|
|
||||||
|
@never_cache
|
||||||
def index(self, request, extra_context=None):
|
def index(self, request, extra_context=None):
|
||||||
"""
|
"""
|
||||||
Displays the main admin index page, which lists all of the installed
|
Displays the main admin index page, which lists all of the installed
|
||||||
|
@ -396,21 +374,6 @@ class AdminSite(object):
|
||||||
return render_to_response(self.index_template or 'admin/index.html', context,
|
return render_to_response(self.index_template or 'admin/index.html', context,
|
||||||
context_instance=context_instance
|
context_instance=context_instance
|
||||||
)
|
)
|
||||||
index = never_cache(index)
|
|
||||||
|
|
||||||
def display_login_form(self, request, error_message='', extra_context=None):
|
|
||||||
request.session.set_test_cookie()
|
|
||||||
context = {
|
|
||||||
'title': _('Log in'),
|
|
||||||
'app_path': request.get_full_path(),
|
|
||||||
'error_message': error_message,
|
|
||||||
'root_path': self.root_path,
|
|
||||||
}
|
|
||||||
context.update(extra_context or {})
|
|
||||||
context_instance = template.RequestContext(request, current_app=self.name)
|
|
||||||
return render_to_response(self.login_template or 'admin/login.html', context,
|
|
||||||
context_instance=context_instance
|
|
||||||
)
|
|
||||||
|
|
||||||
def app_index(self, request, app_label, extra_context=None):
|
def app_index(self, request, app_label, extra_context=None):
|
||||||
user = request.user
|
user = request.user
|
||||||
|
|
|
@ -12,17 +12,31 @@
|
||||||
{% block breadcrumbs %}{% endblock %}
|
{% block breadcrumbs %}{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% if error_message %}
|
{% if form.errors and not form.non_field_errors and not form.this_is_the_login_form.errors %}
|
||||||
<p class="errornote">{{ error_message }}</p>
|
<p class="errornote">
|
||||||
|
{% blocktrans count form.errors.items|length as counter %}Please correct the error below.{% plural %}Please correct the errors below.{% endblocktrans %}
|
||||||
|
</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
{% if form.non_field_errors or form.this_is_the_login_form.errors %}
|
||||||
|
{% for error in form.non_field_errors|add:form.this_is_the_login_form.errors %}
|
||||||
|
<p class="errornote">
|
||||||
|
{{ error }}
|
||||||
|
</p>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<div id="content-main">
|
<div id="content-main">
|
||||||
<form action="{{ app_path }}" method="post" id="login-form">{% csrf_token %}
|
<form action="{{ app_path }}" method="post" id="login-form">{% csrf_token %}
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<label for="id_username">{% trans 'Username:' %}</label> <input type="text" name="username" id="id_username" />
|
{% if not form.this_is_the_login_form.errors %}{{ form.username.errors }}{% endif %}
|
||||||
|
<label for="id_username" class="required">{% trans 'Username:' %}</label> {{ form.username }}
|
||||||
</div>
|
</div>
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<label for="id_password">{% trans 'Password:' %}</label> <input type="password" name="password" id="id_password" />
|
{% if not form.this_is_the_login_form.errors %}{{ form.password.errors }}{% endif %}
|
||||||
|
<label for="id_password" class="required">{% trans 'Password:' %}</label> {{ form.password }}
|
||||||
<input type="hidden" name="this_is_the_login_form" value="1" />
|
<input type="hidden" name="this_is_the_login_form" value="1" />
|
||||||
|
<input type="hidden" name="next" value="{{ next }}" />
|
||||||
</div>
|
</div>
|
||||||
<div class="submit-row">
|
<div class="submit-row">
|
||||||
<label> </label><input type="submit" value="{% trans 'Log in' %}" />
|
<label> </label><input type="submit" value="{% trans 'Log in' %}" />
|
||||||
|
|
|
@ -3,22 +3,13 @@ try:
|
||||||
except ImportError:
|
except ImportError:
|
||||||
from django.utils.functional import wraps # Python 2.4 fallback.
|
from django.utils.functional import wraps # Python 2.4 fallback.
|
||||||
|
|
||||||
from django import http, template
|
from django import template
|
||||||
from django.contrib.auth.models import User
|
|
||||||
from django.contrib.auth import authenticate, login
|
|
||||||
from django.shortcuts import render_to_response
|
from django.shortcuts import render_to_response
|
||||||
from django.utils.translation import ugettext_lazy, ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
|
|
||||||
ERROR_MESSAGE = ugettext_lazy("Please enter a correct username and password. Note that both fields are case-sensitive.")
|
from django.contrib.admin.forms import AdminAuthenticationForm
|
||||||
LOGIN_FORM_KEY = 'this_is_the_login_form'
|
from django.contrib.auth.views import login
|
||||||
|
from django.contrib.auth import REDIRECT_FIELD_NAME
|
||||||
def _display_login_form(request, error_message=''):
|
|
||||||
request.session.set_test_cookie()
|
|
||||||
return render_to_response('admin/login.html', {
|
|
||||||
'title': _('Log in'),
|
|
||||||
'app_path': request.get_full_path(),
|
|
||||||
'error_message': error_message
|
|
||||||
}, context_instance=template.RequestContext(request))
|
|
||||||
|
|
||||||
def staff_member_required(view_func):
|
def staff_member_required(view_func):
|
||||||
"""
|
"""
|
||||||
|
@ -31,45 +22,14 @@ def staff_member_required(view_func):
|
||||||
return view_func(request, *args, **kwargs)
|
return view_func(request, *args, **kwargs)
|
||||||
|
|
||||||
assert hasattr(request, 'session'), "The Django admin requires session middleware to be installed. Edit your MIDDLEWARE_CLASSES setting to insert 'django.contrib.sessions.middleware.SessionMiddleware'."
|
assert hasattr(request, 'session'), "The Django admin requires session middleware to be installed. Edit your MIDDLEWARE_CLASSES setting to insert 'django.contrib.sessions.middleware.SessionMiddleware'."
|
||||||
|
defaults = {
|
||||||
# If this isn't already the login page, display it.
|
'template_name': 'admin/login.html',
|
||||||
if LOGIN_FORM_KEY not in request.POST:
|
'authentication_form': AdminAuthenticationForm,
|
||||||
if request.POST:
|
'extra_context': {
|
||||||
message = _("Please log in again, because your session has expired.")
|
'title': _('Log in'),
|
||||||
else:
|
'app_path': request.get_full_path(),
|
||||||
message = ""
|
REDIRECT_FIELD_NAME: request.get_full_path(),
|
||||||
return _display_login_form(request, message)
|
},
|
||||||
|
}
|
||||||
# Check that the user accepts cookies.
|
return login(request, **defaults)
|
||||||
if not request.session.test_cookie_worked():
|
|
||||||
message = _("Looks like your browser isn't configured to accept cookies. Please enable cookies, reload this page, and try again.")
|
|
||||||
return _display_login_form(request, message)
|
|
||||||
else:
|
|
||||||
request.session.delete_test_cookie()
|
|
||||||
|
|
||||||
# Check the password.
|
|
||||||
username = request.POST.get('username', None)
|
|
||||||
password = request.POST.get('password', None)
|
|
||||||
user = authenticate(username=username, password=password)
|
|
||||||
if user is None:
|
|
||||||
message = ERROR_MESSAGE
|
|
||||||
if '@' in username:
|
|
||||||
# Mistakenly entered e-mail address instead of username? Look it up.
|
|
||||||
users = list(User.objects.filter(email=username))
|
|
||||||
if len(users) == 1 and users[0].check_password(password):
|
|
||||||
message = _("Your e-mail address is not your username. Try '%s' instead.") % users[0].username
|
|
||||||
else:
|
|
||||||
# Either we cannot find the user, or if more than 1
|
|
||||||
# we cannot guess which user is the correct one.
|
|
||||||
message = _("Usernames cannot contain the '@' character.")
|
|
||||||
return _display_login_form(request, message)
|
|
||||||
|
|
||||||
# The user data is correct; log in the user in and continue.
|
|
||||||
else:
|
|
||||||
if user.is_active and user.is_staff:
|
|
||||||
login(request, user)
|
|
||||||
return http.HttpResponseRedirect(request.get_full_path())
|
|
||||||
else:
|
|
||||||
return _display_login_form(request, ERROR_MESSAGE)
|
|
||||||
|
|
||||||
return wraps(view_func)(_checklogin)
|
return wraps(view_func)(_checklogin)
|
||||||
|
|
|
@ -87,14 +87,15 @@ class AuthenticationForm(forms.Form):
|
||||||
raise forms.ValidationError(_("Please enter a correct username and password. Note that both fields are case-sensitive."))
|
raise forms.ValidationError(_("Please enter a correct username and password. Note that both fields are case-sensitive."))
|
||||||
elif not self.user_cache.is_active:
|
elif not self.user_cache.is_active:
|
||||||
raise forms.ValidationError(_("This account is inactive."))
|
raise forms.ValidationError(_("This account is inactive."))
|
||||||
|
self.check_for_test_cookie()
|
||||||
# TODO: determine whether this should move to its own method.
|
|
||||||
if self.request:
|
|
||||||
if not self.request.session.test_cookie_worked():
|
|
||||||
raise forms.ValidationError(_("Your Web browser doesn't appear to have cookies enabled. Cookies are required for logging in."))
|
|
||||||
|
|
||||||
return self.cleaned_data
|
return self.cleaned_data
|
||||||
|
|
||||||
|
def check_for_test_cookie(self):
|
||||||
|
if self.request and not self.request.session.test_cookie_worked():
|
||||||
|
raise forms.ValidationError(
|
||||||
|
_("Your Web browser doesn't appear to have cookies enabled. "
|
||||||
|
"Cookies are required for logging in."))
|
||||||
|
|
||||||
def get_user_id(self):
|
def get_user_id(self):
|
||||||
if self.user_cache:
|
if self.user_cache:
|
||||||
return self.user_cache.id
|
return self.user_cache.id
|
||||||
|
|
|
@ -24,7 +24,7 @@ from django.views.decorators.cache import never_cache
|
||||||
def login(request, template_name='registration/login.html',
|
def login(request, template_name='registration/login.html',
|
||||||
redirect_field_name=REDIRECT_FIELD_NAME,
|
redirect_field_name=REDIRECT_FIELD_NAME,
|
||||||
authentication_form=AuthenticationForm,
|
authentication_form=AuthenticationForm,
|
||||||
extra_context=None):
|
current_app=None, extra_context=None):
|
||||||
"""Displays the login form and handles the login action."""
|
"""Displays the login form and handles the login action."""
|
||||||
|
|
||||||
redirect_to = request.REQUEST.get(redirect_field_name, '')
|
redirect_to = request.REQUEST.get(redirect_field_name, '')
|
||||||
|
@ -65,12 +65,12 @@ def login(request, template_name='registration/login.html',
|
||||||
}
|
}
|
||||||
context.update(extra_context or {})
|
context.update(extra_context or {})
|
||||||
return render_to_response(template_name, context,
|
return render_to_response(template_name, context,
|
||||||
context_instance=RequestContext(request))
|
context_instance=RequestContext(request, current_app=current_app))
|
||||||
|
|
||||||
def logout(request, next_page=None,
|
def logout(request, next_page=None,
|
||||||
template_name='registration/logged_out.html',
|
template_name='registration/logged_out.html',
|
||||||
redirect_field_name=REDIRECT_FIELD_NAME,
|
redirect_field_name=REDIRECT_FIELD_NAME,
|
||||||
extra_context=None):
|
current_app=None, extra_context=None):
|
||||||
"Logs out the user and displays 'You are logged out' message."
|
"Logs out the user and displays 'You are logged out' message."
|
||||||
from django.contrib.auth import logout
|
from django.contrib.auth import logout
|
||||||
logout(request)
|
logout(request)
|
||||||
|
@ -87,16 +87,16 @@ def logout(request, next_page=None,
|
||||||
}
|
}
|
||||||
context.update(extra_context or {})
|
context.update(extra_context or {})
|
||||||
return render_to_response(template_name, context,
|
return render_to_response(template_name, context,
|
||||||
context_instance=RequestContext(request))
|
context_instance=RequestContext(request, current_app=current_app))
|
||||||
else:
|
else:
|
||||||
# Redirect to this page until the session has been cleared.
|
# Redirect to this page until the session has been cleared.
|
||||||
return HttpResponseRedirect(next_page or request.path)
|
return HttpResponseRedirect(next_page or request.path)
|
||||||
|
|
||||||
def logout_then_login(request, login_url=None, extra_context=None):
|
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."
|
"Logs out the user if he is logged in. Then redirects to the log-in page."
|
||||||
if not login_url:
|
if not login_url:
|
||||||
login_url = settings.LOGIN_URL
|
login_url = settings.LOGIN_URL
|
||||||
return logout(request, login_url, extra_context=extra_context)
|
return logout(request, login_url, current_app=current_app, extra_context=extra_context)
|
||||||
|
|
||||||
def redirect_to_login(next, login_url=None,
|
def redirect_to_login(next, login_url=None,
|
||||||
redirect_field_name=REDIRECT_FIELD_NAME):
|
redirect_field_name=REDIRECT_FIELD_NAME):
|
||||||
|
@ -127,6 +127,7 @@ def password_reset(request, is_admin_site=False,
|
||||||
token_generator=default_token_generator,
|
token_generator=default_token_generator,
|
||||||
post_reset_redirect=None,
|
post_reset_redirect=None,
|
||||||
from_email=None,
|
from_email=None,
|
||||||
|
current_app=None,
|
||||||
extra_context=None):
|
extra_context=None):
|
||||||
if post_reset_redirect is None:
|
if post_reset_redirect is None:
|
||||||
post_reset_redirect = reverse('django.contrib.auth.views.password_reset_done')
|
post_reset_redirect = reverse('django.contrib.auth.views.password_reset_done')
|
||||||
|
@ -151,15 +152,15 @@ def password_reset(request, is_admin_site=False,
|
||||||
}
|
}
|
||||||
context.update(extra_context or {})
|
context.update(extra_context or {})
|
||||||
return render_to_response(template_name, context,
|
return render_to_response(template_name, context,
|
||||||
context_instance=RequestContext(request))
|
context_instance=RequestContext(request, current_app=current_app))
|
||||||
|
|
||||||
def password_reset_done(request,
|
def password_reset_done(request,
|
||||||
template_name='registration/password_reset_done.html',
|
template_name='registration/password_reset_done.html',
|
||||||
extra_context=None):
|
current_app=None, extra_context=None):
|
||||||
context = {}
|
context = {}
|
||||||
context.update(extra_context or {})
|
context.update(extra_context or {})
|
||||||
return render_to_response(template_name, context,
|
return render_to_response(template_name, context,
|
||||||
context_instance=RequestContext(request))
|
context_instance=RequestContext(request, current_app=current_app))
|
||||||
|
|
||||||
# Doesn't need csrf_protect since no-one can guess the URL
|
# Doesn't need csrf_protect since no-one can guess the URL
|
||||||
def password_reset_confirm(request, uidb36=None, token=None,
|
def password_reset_confirm(request, uidb36=None, token=None,
|
||||||
|
@ -167,7 +168,7 @@ def password_reset_confirm(request, uidb36=None, token=None,
|
||||||
token_generator=default_token_generator,
|
token_generator=default_token_generator,
|
||||||
set_password_form=SetPasswordForm,
|
set_password_form=SetPasswordForm,
|
||||||
post_reset_redirect=None,
|
post_reset_redirect=None,
|
||||||
extra_context=None):
|
current_app=None, extra_context=None):
|
||||||
"""
|
"""
|
||||||
View that checks the hash in a password reset link and presents a
|
View that checks the hash in a password reset link and presents a
|
||||||
form for entering a new password.
|
form for entering a new password.
|
||||||
|
@ -199,17 +200,17 @@ def password_reset_confirm(request, uidb36=None, token=None,
|
||||||
}
|
}
|
||||||
context.update(extra_context or {})
|
context.update(extra_context or {})
|
||||||
return render_to_response(template_name, context,
|
return render_to_response(template_name, context,
|
||||||
context_instance=RequestContext(request))
|
context_instance=RequestContext(request, current_app=current_app))
|
||||||
|
|
||||||
def password_reset_complete(request,
|
def password_reset_complete(request,
|
||||||
template_name='registration/password_reset_complete.html',
|
template_name='registration/password_reset_complete.html',
|
||||||
extra_context=None):
|
current_app=None, extra_context=None):
|
||||||
context = {
|
context = {
|
||||||
'login_url': settings.LOGIN_URL
|
'login_url': settings.LOGIN_URL
|
||||||
}
|
}
|
||||||
context.update(extra_context or {})
|
context.update(extra_context or {})
|
||||||
return render_to_response(template_name, context,
|
return render_to_response(template_name, context,
|
||||||
context_instance=RequestContext(request))
|
context_instance=RequestContext(request, current_app=current_app))
|
||||||
|
|
||||||
@csrf_protect
|
@csrf_protect
|
||||||
@login_required
|
@login_required
|
||||||
|
@ -217,7 +218,7 @@ def password_change(request,
|
||||||
template_name='registration/password_change_form.html',
|
template_name='registration/password_change_form.html',
|
||||||
post_change_redirect=None,
|
post_change_redirect=None,
|
||||||
password_change_form=PasswordChangeForm,
|
password_change_form=PasswordChangeForm,
|
||||||
extra_context=None):
|
current_app=None, extra_context=None):
|
||||||
if post_change_redirect is None:
|
if post_change_redirect is None:
|
||||||
post_change_redirect = reverse('django.contrib.auth.views.password_change_done')
|
post_change_redirect = reverse('django.contrib.auth.views.password_change_done')
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
|
@ -232,12 +233,12 @@ def password_change(request,
|
||||||
}
|
}
|
||||||
context.update(extra_context or {})
|
context.update(extra_context or {})
|
||||||
return render_to_response(template_name, context,
|
return render_to_response(template_name, context,
|
||||||
context_instance=RequestContext(request))
|
context_instance=RequestContext(request, current_app=current_app))
|
||||||
|
|
||||||
def password_change_done(request,
|
def password_change_done(request,
|
||||||
template_name='registration/password_change_done.html',
|
template_name='registration/password_change_done.html',
|
||||||
extra_context=None):
|
current_app=None, extra_context=None):
|
||||||
context = {}
|
context = {}
|
||||||
context.update(extra_context or {})
|
context.update(extra_context or {})
|
||||||
return render_to_response(template_name, context,
|
return render_to_response(template_name, context,
|
||||||
context_instance=RequestContext(request))
|
context_instance=RequestContext(request, current_app=current_app))
|
||||||
|
|
|
@ -1459,6 +1459,13 @@ Path to a custom template that will be used by the admin site main index view.
|
||||||
|
|
||||||
Path to a custom template that will be used by the admin site login view.
|
Path to a custom template that will be used by the admin site login view.
|
||||||
|
|
||||||
|
.. versionadded:: 1.3
|
||||||
|
|
||||||
|
.. attribute:: AdminSite.login_form
|
||||||
|
|
||||||
|
Subclass of :class:`~django.contrib.auth.forms.AuthenticationForm` that will
|
||||||
|
be used by the admin site login view.
|
||||||
|
|
||||||
.. attribute:: AdminSite.logout_template
|
.. attribute:: AdminSite.logout_template
|
||||||
|
|
||||||
.. versionadded:: 1.2
|
.. versionadded:: 1.2
|
||||||
|
|
|
@ -95,6 +95,23 @@ As a result, we took the following steps to rectify the issue:
|
||||||
**if the value is not None**, and falls back to the previously used
|
**if the value is not None**, and falls back to the previously used
|
||||||
:setting:`MEDIA_URL` setting otherwise.
|
:setting:`MEDIA_URL` setting otherwise.
|
||||||
|
|
||||||
|
Changes to the login methods of the admin
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
In previous version the admin app defined login methods in multiple locations
|
||||||
|
and ignored the almost identical implementation in the already used auth app.
|
||||||
|
A side effect of this duplication was the missing adoption of the changes made
|
||||||
|
in r12634_ to support a broader set of characters for usernames.
|
||||||
|
|
||||||
|
This release refactores the admin's login mechanism to use a subclass of the
|
||||||
|
:class:`~django.contrib.auth.forms.AuthenticationForm` instead of a manual
|
||||||
|
form validation. The previously undocumented method
|
||||||
|
``'django.contrib.admin.sites.AdminSite.display_login_form'`` has been removed
|
||||||
|
in favor of a new :attr:`~django.contrib.admin.AdminSite.login_form`
|
||||||
|
attribute.
|
||||||
|
|
||||||
|
.. _r12634: http://code.djangoproject.com/changeset/12634
|
||||||
|
|
||||||
The Django 1.3 roadmap
|
The Django 1.3 roadmap
|
||||||
======================
|
======================
|
||||||
|
|
||||||
|
|
|
@ -424,3 +424,20 @@ Django 1.5, the old behavior will be replaced with the new behavior.
|
||||||
To ensure compatibility with future versions of Django, existing
|
To ensure compatibility with future versions of Django, existing
|
||||||
templates should be modified to use the new ``future`` libraries and
|
templates should be modified to use the new ``future`` libraries and
|
||||||
syntax.
|
syntax.
|
||||||
|
|
||||||
|
Changes to the login methods of the admin
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
In previous version the admin app defined login methods in multiple locations
|
||||||
|
and ignored the almost identical implementation in the already used auth app.
|
||||||
|
A side effect of this duplication was the missing adoption of the changes made
|
||||||
|
in r12634_ to support a broader set of characters for usernames.
|
||||||
|
|
||||||
|
This release refactores the admin's login mechanism to use a subclass of the
|
||||||
|
:class:`~django.contrib.auth.forms.AuthenticationForm` instead of a manual
|
||||||
|
form validation. The previously undocumented method
|
||||||
|
``'django.contrib.admin.sites.AdminSite.display_login_form'`` has been removed
|
||||||
|
in favor of a new :attr:`~django.contrib.admin.AdminSite.login_form`
|
||||||
|
attribute.
|
||||||
|
|
||||||
|
.. _r12634: http://code.djangoproject.com/changeset/12634
|
||||||
|
|
|
@ -5,9 +5,10 @@ from django.conf.urls.defaults import patterns
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
|
|
||||||
import models
|
import models, forms
|
||||||
|
|
||||||
class Admin2(admin.AdminSite):
|
class Admin2(admin.AdminSite):
|
||||||
|
login_form = forms.CustomAdminAuthenticationForm
|
||||||
login_template = 'custom_admin/login.html'
|
login_template = 'custom_admin/login.html'
|
||||||
logout_template = 'custom_admin/logout.html'
|
logout_template = 'custom_admin/logout.html'
|
||||||
index_template = 'custom_admin/index.html'
|
index_template = 'custom_admin/index.html'
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
from django import forms
|
||||||
|
from django.contrib.admin.forms import AdminAuthenticationForm
|
||||||
|
|
||||||
|
class CustomAdminAuthenticationForm(AdminAuthenticationForm):
|
||||||
|
|
||||||
|
def clean_username(self):
|
||||||
|
username = self.cleaned_data.get('username')
|
||||||
|
if username == 'customform':
|
||||||
|
raise forms.ValidationError('custom form error')
|
||||||
|
return username
|
|
@ -5,7 +5,7 @@ import datetime
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core import mail
|
from django.core import mail
|
||||||
from django.core.files import temp as tempfile
|
from django.core.files import temp as tempfile
|
||||||
from django.contrib.auth import admin # Register auth models with the admin.
|
from django.contrib.auth import REDIRECT_FIELD_NAME, admin # Register auth models with the admin.
|
||||||
from django.contrib.auth.models import User, Permission, UNUSABLE_PASSWORD
|
from django.contrib.auth.models import User, Permission, UNUSABLE_PASSWORD
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.contrib.admin.models import LogEntry, DELETION
|
from django.contrib.admin.models import LogEntry, DELETION
|
||||||
|
@ -377,6 +377,19 @@ class SaveAsTests(TestCase):
|
||||||
class CustomModelAdminTest(AdminViewBasicTest):
|
class CustomModelAdminTest(AdminViewBasicTest):
|
||||||
urlbit = "admin2"
|
urlbit = "admin2"
|
||||||
|
|
||||||
|
def testCustomAdminSiteLoginForm(self):
|
||||||
|
self.client.logout()
|
||||||
|
request = self.client.get('/test_admin/admin2/')
|
||||||
|
self.failUnlessEqual(request.status_code, 200)
|
||||||
|
login = self.client.post('/test_admin/admin2/', {
|
||||||
|
REDIRECT_FIELD_NAME: '/test_admin/admin2/',
|
||||||
|
LOGIN_FORM_KEY: 1,
|
||||||
|
'username': 'customform',
|
||||||
|
'password': 'secret',
|
||||||
|
})
|
||||||
|
self.failUnlessEqual(login.status_code, 200)
|
||||||
|
self.assertContains(login, 'custom form error')
|
||||||
|
|
||||||
def testCustomAdminSiteLoginTemplate(self):
|
def testCustomAdminSiteLoginTemplate(self):
|
||||||
self.client.logout()
|
self.client.logout()
|
||||||
request = self.client.get('/test_admin/admin2/')
|
request = self.client.get('/test_admin/admin2/')
|
||||||
|
@ -446,36 +459,52 @@ class AdminViewPermissionsTest(TestCase):
|
||||||
|
|
||||||
# login POST dicts
|
# login POST dicts
|
||||||
self.super_login = {
|
self.super_login = {
|
||||||
LOGIN_FORM_KEY: 1,
|
REDIRECT_FIELD_NAME: '/test_admin/admin/',
|
||||||
'username': 'super',
|
LOGIN_FORM_KEY: 1,
|
||||||
'password': 'secret'}
|
'username': 'super',
|
||||||
|
'password': 'secret',
|
||||||
|
}
|
||||||
self.super_email_login = {
|
self.super_email_login = {
|
||||||
LOGIN_FORM_KEY: 1,
|
REDIRECT_FIELD_NAME: '/test_admin/admin/',
|
||||||
'username': 'super@example.com',
|
LOGIN_FORM_KEY: 1,
|
||||||
'password': 'secret'}
|
'username': 'super@example.com',
|
||||||
|
'password': 'secret',
|
||||||
|
}
|
||||||
self.super_email_bad_login = {
|
self.super_email_bad_login = {
|
||||||
LOGIN_FORM_KEY: 1,
|
REDIRECT_FIELD_NAME: '/test_admin/admin/',
|
||||||
'username': 'super@example.com',
|
LOGIN_FORM_KEY: 1,
|
||||||
'password': 'notsecret'}
|
'username': 'super@example.com',
|
||||||
|
'password': 'notsecret',
|
||||||
|
}
|
||||||
self.adduser_login = {
|
self.adduser_login = {
|
||||||
LOGIN_FORM_KEY: 1,
|
REDIRECT_FIELD_NAME: '/test_admin/admin/',
|
||||||
'username': 'adduser',
|
LOGIN_FORM_KEY: 1,
|
||||||
'password': 'secret'}
|
'username': 'adduser',
|
||||||
|
'password': 'secret',
|
||||||
|
}
|
||||||
self.changeuser_login = {
|
self.changeuser_login = {
|
||||||
LOGIN_FORM_KEY: 1,
|
REDIRECT_FIELD_NAME: '/test_admin/admin/',
|
||||||
'username': 'changeuser',
|
LOGIN_FORM_KEY: 1,
|
||||||
'password': 'secret'}
|
'username': 'changeuser',
|
||||||
|
'password': 'secret',
|
||||||
|
}
|
||||||
self.deleteuser_login = {
|
self.deleteuser_login = {
|
||||||
LOGIN_FORM_KEY: 1,
|
REDIRECT_FIELD_NAME: '/test_admin/admin/',
|
||||||
'username': 'deleteuser',
|
LOGIN_FORM_KEY: 1,
|
||||||
'password': 'secret'}
|
'username': 'deleteuser',
|
||||||
|
'password': 'secret',
|
||||||
|
}
|
||||||
self.joepublic_login = {
|
self.joepublic_login = {
|
||||||
LOGIN_FORM_KEY: 1,
|
REDIRECT_FIELD_NAME: '/test_admin/admin/',
|
||||||
'username': 'joepublic',
|
LOGIN_FORM_KEY: 1,
|
||||||
'password': 'secret'}
|
'username': 'joepublic',
|
||||||
|
'password': 'secret',
|
||||||
|
}
|
||||||
self.no_username_login = {
|
self.no_username_login = {
|
||||||
LOGIN_FORM_KEY: 1,
|
REDIRECT_FIELD_NAME: '/test_admin/admin/',
|
||||||
'password': 'secret'}
|
LOGIN_FORM_KEY: 1,
|
||||||
|
'password': 'secret',
|
||||||
|
}
|
||||||
|
|
||||||
def testLogin(self):
|
def testLogin(self):
|
||||||
"""
|
"""
|
||||||
|
@ -500,12 +529,12 @@ class AdminViewPermissionsTest(TestCase):
|
||||||
self.assertContains(login, "Your e-mail address is not your username")
|
self.assertContains(login, "Your e-mail address is not your username")
|
||||||
# only correct passwords get a username hint
|
# only correct passwords get a username hint
|
||||||
login = self.client.post('/test_admin/admin/', self.super_email_bad_login)
|
login = self.client.post('/test_admin/admin/', self.super_email_bad_login)
|
||||||
self.assertContains(login, "Usernames cannot contain the '@' character")
|
self.assertContains(login, "Please enter a correct username and password.")
|
||||||
new_user = User(username='jondoe', password='secret', email='super@example.com')
|
new_user = User(username='jondoe', password='secret', email='super@example.com')
|
||||||
new_user.save()
|
new_user.save()
|
||||||
# check to ensure if there are multiple e-mail addresses a user doesn't get a 500
|
# check to ensure if there are multiple e-mail addresses a user doesn't get a 500
|
||||||
login = self.client.post('/test_admin/admin/', self.super_email_login)
|
login = self.client.post('/test_admin/admin/', self.super_email_login)
|
||||||
self.assertContains(login, "Usernames cannot contain the '@' character")
|
self.assertContains(login, "Please enter a correct username and password.")
|
||||||
|
|
||||||
# Add User
|
# Add User
|
||||||
request = self.client.get('/test_admin/admin/')
|
request = self.client.get('/test_admin/admin/')
|
||||||
|
@ -536,23 +565,24 @@ class AdminViewPermissionsTest(TestCase):
|
||||||
self.failUnlessEqual(request.status_code, 200)
|
self.failUnlessEqual(request.status_code, 200)
|
||||||
login = self.client.post('/test_admin/admin/', self.joepublic_login)
|
login = self.client.post('/test_admin/admin/', self.joepublic_login)
|
||||||
self.failUnlessEqual(login.status_code, 200)
|
self.failUnlessEqual(login.status_code, 200)
|
||||||
# Login.context is a list of context dicts we just need to check the first one.
|
self.assertContains(login, "Please enter a correct username and password.")
|
||||||
self.assert_(login.context[0].get('error_message'))
|
|
||||||
|
|
||||||
# Requests without username should not return 500 errors.
|
# Requests without username should not return 500 errors.
|
||||||
request = self.client.get('/test_admin/admin/')
|
request = self.client.get('/test_admin/admin/')
|
||||||
self.failUnlessEqual(request.status_code, 200)
|
self.failUnlessEqual(request.status_code, 200)
|
||||||
login = self.client.post('/test_admin/admin/', self.no_username_login)
|
login = self.client.post('/test_admin/admin/', self.no_username_login)
|
||||||
self.failUnlessEqual(login.status_code, 200)
|
self.failUnlessEqual(login.status_code, 200)
|
||||||
# Login.context is a list of context dicts we just need to check the first one.
|
form = login.context[0].get('form')
|
||||||
self.assert_(login.context[0].get('error_message'))
|
self.failUnlessEqual(form.errors['username'][0], 'This field is required.')
|
||||||
|
|
||||||
def testLoginSuccessfullyRedirectsToOriginalUrl(self):
|
def testLoginSuccessfullyRedirectsToOriginalUrl(self):
|
||||||
request = self.client.get('/test_admin/admin/')
|
request = self.client.get('/test_admin/admin/')
|
||||||
self.failUnlessEqual(request.status_code, 200)
|
self.failUnlessEqual(request.status_code, 200)
|
||||||
query_string = "the-answer=42"
|
query_string = 'the-answer=42'
|
||||||
login = self.client.post('/test_admin/admin/', self.super_login, QUERY_STRING = query_string )
|
redirect_url = '/test_admin/admin/?%s' % query_string
|
||||||
self.assertRedirects(login, '/test_admin/admin/?%s' % query_string)
|
new_next = {REDIRECT_FIELD_NAME: redirect_url}
|
||||||
|
login = self.client.post('/test_admin/admin/', dict(self.super_login, **new_next), QUERY_STRING=query_string)
|
||||||
|
self.assertRedirects(login, redirect_url)
|
||||||
|
|
||||||
def testAddView(self):
|
def testAddView(self):
|
||||||
"""Test add view restricts access and actually adds items."""
|
"""Test add view restricts access and actually adds items."""
|
||||||
|
@ -967,33 +997,47 @@ class SecureViewTest(TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
# login POST dicts
|
# login POST dicts
|
||||||
self.super_login = {
|
self.super_login = {
|
||||||
LOGIN_FORM_KEY: 1,
|
LOGIN_FORM_KEY: 1,
|
||||||
'username': 'super',
|
REDIRECT_FIELD_NAME: '/test_admin/admin/secure-view/',
|
||||||
'password': 'secret'}
|
'username': 'super',
|
||||||
|
'password': 'secret',
|
||||||
|
}
|
||||||
self.super_email_login = {
|
self.super_email_login = {
|
||||||
LOGIN_FORM_KEY: 1,
|
LOGIN_FORM_KEY: 1,
|
||||||
'username': 'super@example.com',
|
REDIRECT_FIELD_NAME: '/test_admin/admin/secure-view/',
|
||||||
'password': 'secret'}
|
'username': 'super@example.com',
|
||||||
|
'password': 'secret',
|
||||||
|
}
|
||||||
self.super_email_bad_login = {
|
self.super_email_bad_login = {
|
||||||
LOGIN_FORM_KEY: 1,
|
LOGIN_FORM_KEY: 1,
|
||||||
'username': 'super@example.com',
|
REDIRECT_FIELD_NAME: '/test_admin/admin/secure-view/',
|
||||||
'password': 'notsecret'}
|
'username': 'super@example.com',
|
||||||
|
'password': 'notsecret',
|
||||||
|
}
|
||||||
self.adduser_login = {
|
self.adduser_login = {
|
||||||
LOGIN_FORM_KEY: 1,
|
LOGIN_FORM_KEY: 1,
|
||||||
'username': 'adduser',
|
REDIRECT_FIELD_NAME: '/test_admin/admin/secure-view/',
|
||||||
'password': 'secret'}
|
'username': 'adduser',
|
||||||
|
'password': 'secret',
|
||||||
|
}
|
||||||
self.changeuser_login = {
|
self.changeuser_login = {
|
||||||
LOGIN_FORM_KEY: 1,
|
LOGIN_FORM_KEY: 1,
|
||||||
'username': 'changeuser',
|
REDIRECT_FIELD_NAME: '/test_admin/admin/secure-view/',
|
||||||
'password': 'secret'}
|
'username': 'changeuser',
|
||||||
|
'password': 'secret',
|
||||||
|
}
|
||||||
self.deleteuser_login = {
|
self.deleteuser_login = {
|
||||||
LOGIN_FORM_KEY: 1,
|
LOGIN_FORM_KEY: 1,
|
||||||
'username': 'deleteuser',
|
REDIRECT_FIELD_NAME: '/test_admin/admin/secure-view/',
|
||||||
'password': 'secret'}
|
'username': 'deleteuser',
|
||||||
|
'password': 'secret',
|
||||||
|
}
|
||||||
self.joepublic_login = {
|
self.joepublic_login = {
|
||||||
LOGIN_FORM_KEY: 1,
|
LOGIN_FORM_KEY: 1,
|
||||||
'username': 'joepublic',
|
REDIRECT_FIELD_NAME: '/test_admin/admin/secure-view/',
|
||||||
'password': 'secret'}
|
'username': 'joepublic',
|
||||||
|
'password': 'secret',
|
||||||
|
}
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
self.client.logout()
|
self.client.logout()
|
||||||
|
@ -1006,9 +1050,11 @@ class SecureViewTest(TestCase):
|
||||||
def test_secure_view_login_successfully_redirects_to_original_url(self):
|
def test_secure_view_login_successfully_redirects_to_original_url(self):
|
||||||
request = self.client.get('/test_admin/admin/secure-view/')
|
request = self.client.get('/test_admin/admin/secure-view/')
|
||||||
self.failUnlessEqual(request.status_code, 200)
|
self.failUnlessEqual(request.status_code, 200)
|
||||||
query_string = "the-answer=42"
|
query_string = 'the-answer=42'
|
||||||
login = self.client.post('/test_admin/admin/secure-view/', self.super_login, QUERY_STRING = query_string )
|
redirect_url = '/test_admin/admin/secure-view/?%s' % query_string
|
||||||
self.assertRedirects(login, '/test_admin/admin/secure-view/?%s' % query_string)
|
new_next = {REDIRECT_FIELD_NAME: redirect_url}
|
||||||
|
login = self.client.post('/test_admin/admin/secure-view/', dict(self.super_login, **new_next), QUERY_STRING=query_string)
|
||||||
|
self.assertRedirects(login, redirect_url)
|
||||||
|
|
||||||
def test_staff_member_required_decorator_works_as_per_admin_login(self):
|
def test_staff_member_required_decorator_works_as_per_admin_login(self):
|
||||||
"""
|
"""
|
||||||
|
@ -1035,12 +1081,12 @@ class SecureViewTest(TestCase):
|
||||||
self.assertContains(login, "Your e-mail address is not your username")
|
self.assertContains(login, "Your e-mail address is not your username")
|
||||||
# only correct passwords get a username hint
|
# only correct passwords get a username hint
|
||||||
login = self.client.post('/test_admin/admin/secure-view/', self.super_email_bad_login)
|
login = self.client.post('/test_admin/admin/secure-view/', self.super_email_bad_login)
|
||||||
self.assertContains(login, "Usernames cannot contain the '@' character")
|
self.assertContains(login, "Please enter a correct username and password.")
|
||||||
new_user = User(username='jondoe', password='secret', email='super@example.com')
|
new_user = User(username='jondoe', password='secret', email='super@example.com')
|
||||||
new_user.save()
|
new_user.save()
|
||||||
# check to ensure if there are multiple e-mail addresses a user doesn't get a 500
|
# check to ensure if there are multiple e-mail addresses a user doesn't get a 500
|
||||||
login = self.client.post('/test_admin/admin/secure-view/', self.super_email_login)
|
login = self.client.post('/test_admin/admin/secure-view/', self.super_email_login)
|
||||||
self.assertContains(login, "Usernames cannot contain the '@' character")
|
self.assertContains(login, "Please enter a correct username and password.")
|
||||||
|
|
||||||
# Add User
|
# Add User
|
||||||
request = self.client.get('/test_admin/admin/secure-view/')
|
request = self.client.get('/test_admin/admin/secure-view/')
|
||||||
|
@ -1072,7 +1118,7 @@ class SecureViewTest(TestCase):
|
||||||
login = self.client.post('/test_admin/admin/secure-view/', self.joepublic_login)
|
login = self.client.post('/test_admin/admin/secure-view/', self.joepublic_login)
|
||||||
self.failUnlessEqual(login.status_code, 200)
|
self.failUnlessEqual(login.status_code, 200)
|
||||||
# Login.context is a list of context dicts we just need to check the first one.
|
# Login.context is a list of context dicts we just need to check the first one.
|
||||||
self.assert_(login.context[0].get('error_message'))
|
self.assertContains(login, "Please enter a correct username and password.")
|
||||||
|
|
||||||
# 8509 - if a normal user is already logged in, it is possible
|
# 8509 - if a normal user is already logged in, it is possible
|
||||||
# to change user into the superuser without error
|
# to change user into the superuser without error
|
||||||
|
|
Loading…
Reference in New Issue