mirror of
https://github.com/django/django.git
synced 2025-06-05 11:39:13 +00:00
Fixed #12103 -- Added AuthenticationForm.confirm_login_allowed to allow customizing the logic policy.
Thanks ejucovy and lasko for work on the patch.
This commit is contained in:
parent
1c3c21b38d
commit
a1889397a9
@ -191,13 +191,28 @@ class AuthenticationForm(forms.Form):
|
|||||||
code='invalid_login',
|
code='invalid_login',
|
||||||
params={'username': self.username_field.verbose_name},
|
params={'username': self.username_field.verbose_name},
|
||||||
)
|
)
|
||||||
elif not self.user_cache.is_active:
|
else:
|
||||||
raise forms.ValidationError(
|
self.confirm_login_allowed(self.user_cache)
|
||||||
self.error_messages['inactive'],
|
|
||||||
code='inactive',
|
|
||||||
)
|
|
||||||
return self.cleaned_data
|
return self.cleaned_data
|
||||||
|
|
||||||
|
def confirm_login_allowed(self, user):
|
||||||
|
"""
|
||||||
|
Controls whether the given User may log in. This is a policy setting,
|
||||||
|
independent of end-user authentication. This default behavior is to
|
||||||
|
allow login by active users, and reject login by inactive users.
|
||||||
|
|
||||||
|
If the given user cannot log in, this method should raise a
|
||||||
|
``forms.ValidationError``.
|
||||||
|
|
||||||
|
If the given user may log in, this method should return None.
|
||||||
|
"""
|
||||||
|
if not user.is_active:
|
||||||
|
raise forms.ValidationError(
|
||||||
|
self.error_messages['inactive'],
|
||||||
|
code='inactive',
|
||||||
|
)
|
||||||
|
|
||||||
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
|
||||||
|
@ -2,6 +2,7 @@ from __future__ import unicode_literals
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
from django import forms
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.contrib.auth.forms import (UserCreationForm, AuthenticationForm,
|
from django.contrib.auth.forms import (UserCreationForm, AuthenticationForm,
|
||||||
@ -131,6 +132,40 @@ class AuthenticationFormTest(TestCase):
|
|||||||
self.assertEqual(form.non_field_errors(),
|
self.assertEqual(form.non_field_errors(),
|
||||||
[force_text(form.error_messages['inactive'])])
|
[force_text(form.error_messages['inactive'])])
|
||||||
|
|
||||||
|
def test_custom_login_allowed_policy(self):
|
||||||
|
# The user is inactive, but our custom form policy allows him to log in.
|
||||||
|
data = {
|
||||||
|
'username': 'inactive',
|
||||||
|
'password': 'password',
|
||||||
|
}
|
||||||
|
|
||||||
|
class AuthenticationFormWithInactiveUsersOkay(AuthenticationForm):
|
||||||
|
def confirm_login_allowed(self, user):
|
||||||
|
pass
|
||||||
|
|
||||||
|
form = AuthenticationFormWithInactiveUsersOkay(None, data)
|
||||||
|
self.assertTrue(form.is_valid())
|
||||||
|
|
||||||
|
# If we want to disallow some logins according to custom logic,
|
||||||
|
# we should raise a django.forms.ValidationError in the form.
|
||||||
|
class PickyAuthenticationForm(AuthenticationForm):
|
||||||
|
def confirm_login_allowed(self, user):
|
||||||
|
if user.username == "inactive":
|
||||||
|
raise forms.ValidationError(_("This user is disallowed."))
|
||||||
|
raise forms.ValidationError(_("Sorry, nobody's allowed in."))
|
||||||
|
|
||||||
|
form = PickyAuthenticationForm(None, data)
|
||||||
|
self.assertFalse(form.is_valid())
|
||||||
|
self.assertEqual(form.non_field_errors(), ['This user is disallowed.'])
|
||||||
|
|
||||||
|
data = {
|
||||||
|
'username': 'testclient',
|
||||||
|
'password': 'password',
|
||||||
|
}
|
||||||
|
form = PickyAuthenticationForm(None, data)
|
||||||
|
self.assertFalse(form.is_valid())
|
||||||
|
self.assertEqual(form.non_field_errors(), ["Sorry, nobody's allowed in."])
|
||||||
|
|
||||||
def test_success(self):
|
def test_success(self):
|
||||||
# The success case
|
# The success case
|
||||||
data = {
|
data = {
|
||||||
|
@ -101,6 +101,10 @@ Minor features
|
|||||||
:class:`~django.middleware.http.ConditionalGetMiddleware` to handle
|
:class:`~django.middleware.http.ConditionalGetMiddleware` to handle
|
||||||
conditional ``GET`` requests for sitemaps which set ``lastmod``.
|
conditional ``GET`` requests for sitemaps which set ``lastmod``.
|
||||||
|
|
||||||
|
* You can override the new :meth:`AuthenticationForm.confirm_login_allowed()
|
||||||
|
<django.contrib.auth.forms.AuthenticationForm.confirm_login_allowed>` method
|
||||||
|
to more easily customize the login policy.
|
||||||
|
|
||||||
Backwards incompatible changes in 1.7
|
Backwards incompatible changes in 1.7
|
||||||
=====================================
|
=====================================
|
||||||
|
|
||||||
|
@ -959,6 +959,40 @@ provides several built-in forms located in :mod:`django.contrib.auth.forms`:
|
|||||||
Takes ``request`` as its first positional argument, which is stored on the
|
Takes ``request`` as its first positional argument, which is stored on the
|
||||||
form instance for use by sub-classes.
|
form instance for use by sub-classes.
|
||||||
|
|
||||||
|
.. method:: confirm_login_allowed(user)
|
||||||
|
|
||||||
|
.. versionadded:: 1.7
|
||||||
|
|
||||||
|
By default, ``AuthenticationForm`` rejects users whose ``is_active`` flag
|
||||||
|
is set to ``False``. You may override this behavior with a custom policy to
|
||||||
|
determine which users can log in. Do this with a custom form that subclasses
|
||||||
|
``AuthenticationForm`` and overrides the ``confirm_login_allowed`` method.
|
||||||
|
This method should raise a :exc:`~django.core.exceptions.ValidationError`
|
||||||
|
if the given user may not log in.
|
||||||
|
|
||||||
|
For example, to allow all users to log in, regardless of "active" status::
|
||||||
|
|
||||||
|
from django.contrib.auth.forms import AuthenticationForm
|
||||||
|
|
||||||
|
class AuthenticationFormWithInactiveUsersOkay(AuthenticationForm):
|
||||||
|
def confirm_login_allowed(self, user):
|
||||||
|
pass
|
||||||
|
|
||||||
|
Or to allow only some active users to log in::
|
||||||
|
|
||||||
|
class PickyAuthenticationForm(AuthenticationForm):
|
||||||
|
def confirm_login_allowed(self, user):
|
||||||
|
if not user.is_active:
|
||||||
|
raise forms.ValidationError(
|
||||||
|
_("This account is inactive."),
|
||||||
|
code='inactive',
|
||||||
|
)
|
||||||
|
if user.username.startswith('b'):
|
||||||
|
raise forms.ValidationError(
|
||||||
|
_("Sorry, accounts starting with 'b' aren't welcome here."),
|
||||||
|
code='no_b_users',
|
||||||
|
)
|
||||||
|
|
||||||
.. class:: PasswordChangeForm
|
.. class:: PasswordChangeForm
|
||||||
|
|
||||||
A form for allowing a user to change their password.
|
A form for allowing a user to change their password.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user