diff --git a/django/contrib/admin/forms.py b/django/contrib/admin/forms.py index 6814fc9083..05788d9cb1 100644 --- a/django/contrib/admin/forms.py +++ b/django/contrib/admin/forms.py @@ -4,30 +4,23 @@ from django import forms from django.contrib.auth import authenticate from django.contrib.auth.forms import AuthenticationForm -from django.utils.translation import ugettext_lazy - -ERROR_MESSAGE = ugettext_lazy("Please enter the correct %(username)s and password " - "for a staff account. Note that both fields may be case-sensitive.") +from django.utils.translation import ugettext_lazy as _ 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.")}) + error_messages = { + 'invalid_login': _("Please enter the correct %(username)s and password " + "for a staff account. Note that both fields may be " + "case-sensitive."), + } - def clean(self): - username = self.cleaned_data.get('username') - password = self.cleaned_data.get('password') - message = ERROR_MESSAGE - params = {'username': self.username_field.verbose_name} - - if username and password: - self.user_cache = authenticate(username=username, password=password) - if self.user_cache is None: - raise forms.ValidationError(message, code='invalid', params=params) - elif not self.user_cache.is_active or not self.user_cache.is_staff: - raise forms.ValidationError(message, code='invalid', params=params) - return self.cleaned_data + def confirm_login_allowed(self, user): + if not user.is_active or not user.is_staff: + raise forms.ValidationError( + self.error_messages['invalid_login'], + code='invalid_login', + params={'username': self.username_field.verbose_name} + ) diff --git a/django/contrib/admin/sites.py b/django/contrib/admin/sites.py index 3d12b25d36..b83c2e3203 100644 --- a/django/contrib/admin/sites.py +++ b/django/contrib/admin/sites.py @@ -15,8 +15,6 @@ from django.utils.translation import ugettext_lazy, ugettext as _ from django.views.decorators.cache import never_cache from django.conf import settings -LOGIN_FORM_KEY = 'this_is_the_login_form' - class AlreadyRegistered(Exception): pass @@ -193,8 +191,6 @@ class AdminSite(object): cacheable=True. """ def inner(request, *args, **kwargs): - if LOGIN_FORM_KEY in request.POST and request.user.is_authenticated(): - auth_logout(request) if not self.has_permission(request): if request.path == reverse('admin:logout', current_app=self.name): index_path = reverse('admin:index', current_app=self.name) diff --git a/django/contrib/admin/templates/admin/login.html b/django/contrib/admin/templates/admin/login.html index 1371514d43..1c8ae35c35 100644 --- a/django/contrib/admin/templates/admin/login.html +++ b/django/contrib/admin/templates/admin/login.html @@ -12,14 +12,14 @@ {% block breadcrumbs %}{% endblock %} {% block content %} -{% if form.errors and not form.non_field_errors and not form.this_is_the_login_form.errors %} +{% if form.errors and not form.non_field_errors %}

{% if form.errors.items|length == 1 %}{% trans "Please correct the error below." %}{% else %}{% trans "Please correct the errors below." %}{% 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 %} +{% if form.non_field_errors %} +{% for error in form.non_field_errors %}

{{ error }}

@@ -29,13 +29,12 @@
{% csrf_token %}
- {% if not form.this_is_the_login_form.errors %}{{ form.username.errors }}{% endif %} + {{ form.username.errors }} {{ form.username }}
- {% if not form.this_is_the_login_form.errors %}{{ form.password.errors }}{% endif %} + {{ form.password.errors }} {{ form.password }} -
{% url 'admin_password_reset' as password_reset_url %} diff --git a/docs/releases/1.7.txt b/docs/releases/1.7.txt index c79841eb4b..41ad106232 100644 --- a/docs/releases/1.7.txt +++ b/docs/releases/1.7.txt @@ -870,6 +870,10 @@ where any unauthorized request to an admin page will be redirected (by HTTP status code 302) to the login page, with the ``next`` parameter set to the referring path. The user will be redirected there after a successful login. +Note also that the admin login form has been updated to not contain the +``this_is_the_login_form`` field (now unused) and the ``ValidationError`` code +has been set to the more regular ``invalid_login`` key. + Miscellaneous ~~~~~~~~~~~~~ diff --git a/tests/admin_views/tests.py b/tests/admin_views/tests.py index a84ae8c3d2..1ea9b4b657 100644 --- a/tests/admin_views/tests.py +++ b/tests/admin_views/tests.py @@ -17,7 +17,6 @@ from django.contrib.auth import get_permission_codename from django.contrib.admin import ModelAdmin from django.contrib.admin.helpers import ACTION_CHECKBOX_NAME from django.contrib.admin.models import LogEntry, DELETION -from django.contrib.admin.sites import LOGIN_FORM_KEY from django.contrib.admin.utils import quote from django.contrib.admin.validation import ModelAdminValidator from django.contrib.admin.views.main import IS_POPUP_VAR @@ -769,7 +768,6 @@ class CustomModelAdminTest(AdminViewBasicTestCase): self.assertEqual(response.status_code, 200) login = self.client.post('/test_admin/admin2/login/', { REDIRECT_FIELD_NAME: '/test_admin/admin2/', - LOGIN_FORM_KEY: 1, 'username': 'customform', 'password': 'secret', }, follow=True) @@ -874,49 +872,41 @@ class AdminViewPermissionsTest(TestCase): # login POST dicts self.super_login = { REDIRECT_FIELD_NAME: '/test_admin/admin/', - LOGIN_FORM_KEY: 1, 'username': 'super', 'password': 'secret', } self.super_email_login = { REDIRECT_FIELD_NAME: '/test_admin/admin/', - LOGIN_FORM_KEY: 1, 'username': 'super@example.com', 'password': 'secret', } self.super_email_bad_login = { REDIRECT_FIELD_NAME: '/test_admin/admin/', - LOGIN_FORM_KEY: 1, 'username': 'super@example.com', 'password': 'notsecret', } self.adduser_login = { REDIRECT_FIELD_NAME: '/test_admin/admin/', - LOGIN_FORM_KEY: 1, 'username': 'adduser', 'password': 'secret', } self.changeuser_login = { REDIRECT_FIELD_NAME: '/test_admin/admin/', - LOGIN_FORM_KEY: 1, 'username': 'changeuser', 'password': 'secret', } self.deleteuser_login = { REDIRECT_FIELD_NAME: '/test_admin/admin/', - LOGIN_FORM_KEY: 1, 'username': 'deleteuser', 'password': 'secret', } self.joepublic_login = { REDIRECT_FIELD_NAME: '/test_admin/admin/', - LOGIN_FORM_KEY: 1, 'username': 'joepublic', 'password': 'secret', } self.no_username_login = { REDIRECT_FIELD_NAME: '/test_admin/admin/', - LOGIN_FORM_KEY: 1, 'password': 'secret', } @@ -1391,7 +1381,6 @@ class AdminViewsNoUrlTest(TestCase): # login POST dict self.changeuser_login = { REDIRECT_FIELD_NAME: '/test_admin/admin/', - LOGIN_FORM_KEY: 1, 'username': 'changeuser', 'password': 'secret', } @@ -2600,7 +2589,6 @@ class AdminCustomQuerysetTest(TestCase): self.pks = [EmptyModel.objects.create().id for i in range(3)] self.super_login = { REDIRECT_FIELD_NAME: '/test_admin/admin/', - LOGIN_FORM_KEY: 1, 'username': 'super', 'password': 'secret', }