Code

Ticket #12103: 12103_at_r17205.diff

File 12103_at_r17205.diff, 5.0 KB (added by ejucovy, 2 years ago)

updated patch for code-drift

Line 
1Index: docs/topics/auth.txt
2===================================================================
3--- docs/topics/auth.txt        (revision 17205)
4+++ docs/topics/auth.txt        (working copy)
5@@ -1210,6 +1210,31 @@
6 
7     A form for logging a user in.
8 
9+    The ``AuthenticationForm`` rejects users whose ``is_active`` flag is set to ``False``.
10+    You may override this behavior with a custom policy to determine which users can log in.
11+    Do this with a custom form that subclasses ``AuthenticationForm`` and overrides the
12+    ``confirm_login_allowed(self, user)`` method.  This method will raise a ``forms.ValidationError``
13+    if the given user may not log in.
14+
15+    For example, to allow all users to log in, regardless of activation status::
16+
17+    .. code-block:: python
18+
19+        class AuthenticationFormWithInactiveUsersOkay(AuthenticationForm):
20+            def confirm_login_allowed(self, user):
21+               pass
22+
23+    Or to allow only some active users to log in:
24+
25+    .. code-block:: python
26+
27+        class PickyAuthenticationForm(AuthenticationForm):
28+            def confirm_login_allowed(self, user):
29+               if not user.is_active:
30+                   raise forms.ValidationError(_("This account is inactive."))
31+               if user.username.startswith('b'):
32+                   raise forms.ValidationError(_("Sorry, accounts starting with 'b' aren't welcome here."))
33+
34 .. class:: PasswordChangeForm
35 
36     A form for allowing a user to change their password.
37Index: django/contrib/auth/tests/forms.py
38===================================================================
39--- django/contrib/auth/tests/forms.py  (revision 17205)
40+++ django/contrib/auth/tests/forms.py  (working copy)
41@@ -115,6 +115,44 @@
42                 self.assertEqual(form.non_field_errors(),
43                                  [force_unicode(form.error_messages['inactive'])])
44 
45+    def test_custom_login_allowed_policy(self):
46+        # The user is inactive, but our custom form policy allows him to log in.
47+        data = {
48+            'username': 'inactive',
49+            'password': 'password',
50+            }
51+
52+        class AuthenticationFormWithInactiveUsersOkay(AuthenticationForm):
53+            def confirm_login_allowed(self, user):
54+                pass
55+
56+        form = AuthenticationFormWithInactiveUsersOkay(None, data)
57+        self.assertTrue(form.is_valid())
58+
59+        # If we want to disallow some logins according to custom logic,
60+        # we should raise a django.forms.ValidationError in the form.
61+        from django.forms import ValidationError
62+        from django.utils.translation import ugettext_lazy as _
63+        class PickyAuthenticationForm(AuthenticationForm):
64+            def confirm_login_allowed(self, user):
65+                if user.username == "inactive":
66+                    raise ValidationError(_("This user is disallowed."))
67+                raise ValidationError(_("Sorry, nobody's allowed in."))
68+       
69+        form = PickyAuthenticationForm(None, data)
70+        self.assertFalse(form.is_valid())
71+        self.assertEqual(form.non_field_errors(),
72+                         [u'This user is disallowed.'])
73+       
74+        data = {
75+            'username': 'testclient',
76+            'password': 'password',
77+            }
78+        form = PickyAuthenticationForm(None, data)
79+        self.assertFalse(form.is_valid())
80+        self.assertEqual(form.non_field_errors(),
81+                         [u"Sorry, nobody's allowed in."])
82+       
83     def test_success(self):
84         # The success case
85         data = {
86Index: django/contrib/auth/forms.py
87===================================================================
88--- django/contrib/auth/forms.py        (revision 17205)
89+++ django/contrib/auth/forms.py        (working copy)
90@@ -145,8 +145,8 @@
91             self.user_cache = authenticate(username=username, password=password)
92             if self.user_cache is None:
93                 raise forms.ValidationError(self.error_messages['invalid_login'])
94-            elif not self.user_cache.is_active:
95-                raise forms.ValidationError(self.error_messages['inactive'])
96+            else:
97+                self.confirm_login_allowed(self.user_cache)
98         self.check_for_test_cookie()
99         return self.cleaned_data
100 
101@@ -154,6 +154,19 @@
102         if self.request and not self.request.session.test_cookie_worked():
103             raise forms.ValidationError(self.error_messages['no_cookies'])
104 
105+    def confirm_login_allowed(self, user):
106+        """
107+        Controls whether the given ``auth.User`` object may log in. This is a policy setting,
108+        independent of end-user authentication. This default behavior is to allow login by
109+        active users, and reject login by inactive users.
110+
111+        If the given user cannot log in, this method should raise a ``forms.ValidationError``.
112+
113+        If the given user may log in, this method should return None.
114+        """
115+        if not user.is_active:
116+            raise forms.ValidationError(self.error_messages['inactive'])
117+
118     def get_user_id(self):
119         if self.user_cache:
120             return self.user_cache.id