Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #14674 -- Prevent user accounts with an unusable password from …

…resetting passwords. Thanks, summerisgone, thejaswi_puthraya and lrekucki.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@16455 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 2619dc828510cf36791fcf87705d2f9ce3176c86 1 parent 821d8aa
Jannis Leidel authored June 26, 2011
20  django/contrib/auth/forms.py
... ...
@@ -1,11 +1,14 @@
1  
-from django.contrib.auth.models import User
  1
+from django import forms
  2
+from django.template import Context, loader
  3
+from django.utils.http import int_to_base36
  4
+from django.utils.itercompat import any
  5
+from django.utils.translation import ugettext_lazy as _
  6
+
  7
+from django.contrib.auth.models import User, UNUSABLE_PASSWORD
2 8
 from django.contrib.auth import authenticate
3 9
 from django.contrib.auth.tokens import default_token_generator
4 10
 from django.contrib.sites.models import get_current_site
5  
-from django.template import Context, loader
6  
-from django import forms
7  
-from django.utils.translation import ugettext_lazy as _
8  
-from django.utils.http import int_to_base36
  11
+
9 12
 
10 13
 class UserCreationForm(forms.ModelForm):
11 14
     """
@@ -114,10 +117,11 @@ def clean_email(self):
114 117
         email = self.cleaned_data["email"]
115 118
         self.users_cache = User.objects.filter(
116 119
                                 email__iexact=email,
117  
-                                is_active=True
118  
-                            )
119  
-        if len(self.users_cache) == 0:
  120
+                                is_active=True)
  121
+        if not len(self.users_cache):
120 122
             raise forms.ValidationError(_("That e-mail address doesn't have an associated user account. Are you sure you've registered?"))
  123
+        if any((user.password == UNUSABLE_PASSWORD) for user in self.users_cache):
  124
+            raise forms.ValidationError(_("The user account associated with this e-mail address cannot reset the password."))
121 125
         return email
122 126
 
123 127
     def save(self, domain_override=None,
94  django/contrib/auth/locale/en/LC_MESSAGES/django.po
@@ -4,7 +4,7 @@ msgid ""
4 4
 msgstr ""
5 5
 "Project-Id-Version: Django\n"
6 6
 "Report-Msgid-Bugs-To: \n"
7  
-"POT-Creation-Date: 2011-06-19 13:08+0200\n"
  7
+"POT-Creation-Date: 2011-06-25 20:39+0200\n"
8 8
 "PO-Revision-Date: 2010-05-13 15:35+0200\n"
9 9
 "Last-Translator: Django team\n"
10 10
 "Language-Team: English <en@li.org>\n"
@@ -37,190 +37,196 @@ msgstr ""
37 37
 msgid "Change password: %s"
38 38
 msgstr ""
39 39
 
40  
-#: forms.py:14 forms.py:48 forms.py:66
  40
+#: forms.py:17 forms.py:51 forms.py:69
41 41
 msgid "Username"
42 42
 msgstr ""
43 43
 
44  
-#: forms.py:15 forms.py:49
  44
+#: forms.py:18 forms.py:52
45 45
 msgid "Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only."
46 46
 msgstr ""
47 47
 
48  
-#: forms.py:16 forms.py:50
  48
+#: forms.py:19 forms.py:53
49 49
 msgid "This value may contain only letters, numbers and @/./+/-/_ characters."
50 50
 msgstr ""
51 51
 
52  
-#: forms.py:17 forms.py:67 forms.py:201
  52
+#: forms.py:20 forms.py:70 forms.py:205
53 53
 msgid "Password"
54 54
 msgstr ""
55 55
 
56  
-#: forms.py:18
  56
+#: forms.py:21
57 57
 msgid "Password confirmation"
58 58
 msgstr ""
59 59
 
60  
-#: forms.py:19
  60
+#: forms.py:22
61 61
 msgid "Enter the same password as above, for verification."
62 62
 msgstr ""
63 63
 
64  
-#: forms.py:31
  64
+#: forms.py:34
65 65
 msgid "A user with that username already exists."
66 66
 msgstr ""
67 67
 
68  
-#: forms.py:37 forms.py:171 forms.py:213
  68
+#: forms.py:40 forms.py:175 forms.py:217
69 69
 msgid "The two password fields didn't match."
70 70
 msgstr ""
71 71
 
72  
-#: forms.py:87
  72
+#: forms.py:90
73 73
 msgid ""
74 74
 "Please enter a correct username and password. Note that both fields are case-"
75 75
 "sensitive."
76 76
 msgstr ""
77 77
 
78  
-#: forms.py:89
  78
+#: forms.py:92
79 79
 msgid "This account is inactive."
80 80
 msgstr ""
81 81
 
82  
-#: forms.py:96
  82
+#: forms.py:99
83 83
 msgid ""
84 84
 "Your Web browser doesn't appear to have cookies enabled. Cookies are "
85 85
 "required for logging in."
86 86
 msgstr ""
87 87
 
88  
-#: forms.py:108
  88
+#: forms.py:111
89 89
 msgid "E-mail"
90 90
 msgstr ""
91 91
 
92  
-#: forms.py:120
  92
+#: forms.py:122
93 93
 msgid ""
94 94
 "That e-mail address doesn't have an associated user account. Are you sure "
95 95
 "you've registered?"
96 96
 msgstr ""
97 97
 
98  
-#: forms.py:159
  98
+#: forms.py:124
  99
+msgid ""
  100
+"The user account associated with this e-mail address cannot reset the "
  101
+"password."
  102
+msgstr ""
  103
+
  104
+#: forms.py:163
99 105
 msgid "New password"
100 106
 msgstr ""
101 107
 
102  
-#: forms.py:160
  108
+#: forms.py:164
103 109
 msgid "New password confirmation"
104 110
 msgstr ""
105 111
 
106  
-#: forms.py:185
  112
+#: forms.py:189
107 113
 msgid "Old password"
108 114
 msgstr ""
109 115
 
110  
-#: forms.py:193
  116
+#: forms.py:197
111 117
 msgid "Your old password was entered incorrectly. Please enter it again."
112 118
 msgstr ""
113 119
 
114  
-#: forms.py:202
  120
+#: forms.py:206
115 121
 msgid "Password (again)"
116 122
 msgstr ""
117 123
 
118  
-#: models.py:77 models.py:105
  124
+#: models.py:94 models.py:122
119 125
 msgid "name"
120 126
 msgstr ""
121 127
 
122  
-#: models.py:79
  128
+#: models.py:96
123 129
 msgid "codename"
124 130
 msgstr ""
125 131
 
126  
-#: models.py:83
  132
+#: models.py:100
127 133
 msgid "permission"
128 134
 msgstr ""
129 135
 
130  
-#: models.py:84 models.py:106
  136
+#: models.py:101 models.py:123
131 137
 msgid "permissions"
132 138
 msgstr ""
133 139
 
134  
-#: models.py:109
  140
+#: models.py:126
135 141
 msgid "group"
136 142
 msgstr ""
137 143
 
138  
-#: models.py:110 models.py:217
  144
+#: models.py:127 models.py:236
139 145
 msgid "groups"
140 146
 msgstr ""
141 147
 
142  
-#: models.py:207
  148
+#: models.py:226
143 149
 msgid "username"
144 150
 msgstr ""
145 151
 
146  
-#: models.py:207
  152
+#: models.py:226
147 153
 msgid ""
148 154
 "Required. 30 characters or fewer. Letters, numbers and @/./+/-/_ characters"
149 155
 msgstr ""
150 156
 
151  
-#: models.py:208
  157
+#: models.py:227
152 158
 msgid "first name"
153 159
 msgstr ""
154 160
 
155  
-#: models.py:209
  161
+#: models.py:228
156 162
 msgid "last name"
157 163
 msgstr ""
158 164
 
159  
-#: models.py:210
  165
+#: models.py:229
160 166
 msgid "e-mail address"
161 167
 msgstr ""
162 168
 
163  
-#: models.py:211
  169
+#: models.py:230
164 170
 msgid "password"
165 171
 msgstr ""
166 172
 
167  
-#: models.py:211
  173
+#: models.py:230
168 174
 msgid ""
169 175
 "Use '[algo]$[salt]$[hexdigest]' or use the <a href=\"password/\">change "
170 176
 "password form</a>."
171 177
 msgstr ""
172 178
 
173  
-#: models.py:212
  179
+#: models.py:231
174 180
 msgid "staff status"
175 181
 msgstr ""
176 182
 
177  
-#: models.py:212
  183
+#: models.py:231
178 184
 msgid "Designates whether the user can log into this admin site."
179 185
 msgstr ""
180 186
 
181  
-#: models.py:213
  187
+#: models.py:232
182 188
 msgid "active"
183 189
 msgstr ""
184 190
 
185  
-#: models.py:213
  191
+#: models.py:232
186 192
 msgid ""
187 193
 "Designates whether this user should be treated as active. Unselect this "
188 194
 "instead of deleting accounts."
189 195
 msgstr ""
190 196
 
191  
-#: models.py:214
  197
+#: models.py:233
192 198
 msgid "superuser status"
193 199
 msgstr ""
194 200
 
195  
-#: models.py:214
  201
+#: models.py:233
196 202
 msgid ""
197 203
 "Designates that this user has all permissions without explicitly assigning "
198 204
 "them."
199 205
 msgstr ""
200 206
 
201  
-#: models.py:215
  207
+#: models.py:234
202 208
 msgid "last login"
203 209
 msgstr ""
204 210
 
205  
-#: models.py:216
  211
+#: models.py:235
206 212
 msgid "date joined"
207 213
 msgstr ""
208 214
 
209  
-#: models.py:218
  215
+#: models.py:237
210 216
 msgid ""
211 217
 "In addition to the permissions manually assigned, this user will also get "
212 218
 "all permissions granted to each group he/she is in."
213 219
 msgstr ""
214 220
 
215  
-#: models.py:219
  221
+#: models.py:238
216 222
 msgid "user permissions"
217 223
 msgstr ""
218 224
 
219  
-#: models.py:223
  225
+#: models.py:242
220 226
 msgid "user"
221 227
 msgstr ""
222 228
 
223  
-#: models.py:224
  229
+#: models.py:243
224 230
 msgid "users"
225 231
 msgstr ""
226 232
 
13  django/contrib/auth/tests/forms.py
@@ -281,3 +281,16 @@ def test_inactive_user(self):
281 281
         user.save()
282 282
         form = PasswordResetForm({'email': email})
283 283
         self.assertFalse(form.is_valid())
  284
+
  285
+
  286
+    def test_unusable_password(self):
  287
+        user = User.objects.create_user('testuser', 'test@example.com', 'test')
  288
+        data = {"email": "test@example.com"}
  289
+        form = PasswordResetForm(data)
  290
+        self.assertTrue(form.is_valid())
  291
+        user.set_unusable_password()
  292
+        user.save()
  293
+        form = PasswordResetForm(data)
  294
+        self.assertFalse(form.is_valid())
  295
+        self.assertEqual(form["email"].errors,
  296
+                         [u"The user account associated with this e-mail address cannot reset the password."])
6  docs/topics/auth.txt
@@ -1011,6 +1011,12 @@ includes a few other useful built-in views located in
1011 1011
 
1012 1012
         * ``form``: The form for resetting the user's password.
1013 1013
 
  1014
+        .. versionchanged:: 1.4
  1015
+            Users flagged with an unusable password (see
  1016
+            :meth:`~django.contrib.auth.models.User.set_unusable_password()`
  1017
+            will not be able to request a password reset to prevent misuse
  1018
+            when using an external authentication source like LDAP.
  1019
+
1014 1020
 .. function:: password_reset_done(request[, template_name])
1015 1021
 
1016 1022
     The page shown after a user has been emailed a link to reset their

0 notes on commit 2619dc8

Please sign in to comment.
Something went wrong with that request. Please try again.