Code

Ticket #6083: auth-uses-newforms-3.diff

File auth-uses-newforms-3.diff, 20.0 KB (added by Michael Newman <newmaniese@…>, 6 years ago)

Fixed reference to comments.auth.py and added fix to admin.templates.admin.auth.user.change_password.html for new forms and slight change to the way contrib.auth.forms.AdminPasswordChangeForm cleans the form, and changed auth.views.py to use AdminPasswordChangeForm instead of the now nonexistent old form way

Line 
1Index: django/contrib/comments/views/comments.py
2===================================================================
3--- django/contrib/comments/views/comments.py   (revision 7109)
4+++ django/contrib/comments/views/comments.py   (working copy)
5@@ -7,7 +7,6 @@
6 from django.template import RequestContext
7 from django.contrib.comments.models import Comment, FreeComment, RATINGS_REQUIRED, RATINGS_OPTIONAL, IS_PUBLIC
8 from django.contrib.contenttypes.models import ContentType
9-from django.contrib.auth.forms import AuthenticationForm
10 from django.http import HttpResponseRedirect
11 from django.utils.text import normalize_newlines
12 from django.conf import settings
13@@ -17,6 +16,47 @@
14 
15 COMMENTS_PER_PAGE = 20
16 
17+
18+class AuthenticationForm(oldforms.Manipulator):
19+    """
20+    Oldforms-based Base class for authenticating users, extended by contrib.comments
21+    """
22+    def __init__(self, request=None):
23+        """
24+        If request is passed in, the manipulator will validate that cookies are
25+        enabled. Note that the request (a HttpRequest object) must have set a
26+        cookie with the key TEST_COOKIE_NAME and value TEST_COOKIE_VALUE before
27+        running this validator.
28+        """
29+        self.request = request
30+        self.fields = [
31+            oldforms.TextField(field_name="username", length=15, max_length=30, is_required=True,
32+                validator_list=[self.isValidUser, self.hasCookiesEnabled]),
33+            oldforms.PasswordField(field_name="password", length=15, max_length=30, is_required=True),
34+        ]
35+        self.user_cache = None
36+
37+    def hasCookiesEnabled(self, field_data, all_data):
38+        if self.request and not self.request.session.test_cookie_worked():
39+            raise validators.ValidationError, _("Your Web browser doesn't appear to have cookies enabled. Cookies are required for logging in.")
40+
41+    def isValidUser(self, field_data, all_data):
42+        username = field_data
43+        password = all_data.get('password', None)
44+        self.user_cache = authenticate(username=username, password=password)
45+        if self.user_cache is None:
46+            raise validators.ValidationError, _("Please enter a correct username and password. Note that both fields are case-sensitive.")
47+        elif not self.user_cache.is_active:
48+            raise validators.ValidationError, _("This account is inactive.")
49+
50+    def get_user_id(self):
51+        if self.user_cache:
52+            return self.user_cache.id
53+        return None
54+
55+    def get_user(self):
56+        return self.user_cache
57+
58 class PublicCommentManipulator(AuthenticationForm):
59     "Manipulator that handles public registered comments"
60     def __init__(self, user, ratings_required, ratings_range, num_rating_choices):
61Index: django/contrib/admin/templates/admin/auth/user/change_password.html
62===================================================================
63--- django/contrib/admin/templates/admin/auth/user/change_password.html (revision 7109)
64+++ django/contrib/admin/templates/admin/auth/user/change_password.html (working copy)
65@@ -27,14 +27,20 @@
66 <p>{% blocktrans with original.username|escape as username %}Enter a new password for the user <strong>{{ username }}</strong>.{% endblocktrans %}</p>
67 
68 <fieldset class="module aligned">
69-
70+{% if form.non_field_errors %}
71+{{form.non_field_errors}}
72+{% endif %}
73 <div class="form-row">
74-  {{ form.password1.html_error_list }}
75+  {% if form.password1.errors %}
76+  {{ form.password1.errors }}
77+  {% endif %}
78   <label for="id_password1" class="required">{% trans 'Password' %}:</label> {{ form.password1 }}
79 </div>
80 
81 <div class="form-row">
82-  {{ form.password2.html_error_list }}
83+  {% if form.password2.errors %}
84+  {{ form.password2.errors }}
85+  {% endif %}
86   <label for="id_password2" class="required">{% trans 'Password (again)' %}:</label> {{ form.password2 }}
87   <p class="help">{% trans 'Enter the same password as above, for verification.' %}</p>
88 </div>
89Index: django/contrib/auth/views.py
90===================================================================
91--- django/contrib/auth/views.py        (revision 7109)
92+++ django/contrib/auth/views.py        (working copy)
93@@ -14,21 +14,21 @@
94 
95 def login(request, template_name='registration/login.html', redirect_field_name=REDIRECT_FIELD_NAME):
96     "Displays the login form and handles the login action."
97-    manipulator = AuthenticationForm(request)
98     redirect_to = request.REQUEST.get(redirect_field_name, '')
99-    if request.POST:
100-        errors = manipulator.get_validation_errors(request.POST)
101-        if not errors:
102+    if request.method == 'POST':
103+        form = AuthenticationForm(request.POST)
104+        if form.is_valid():
105             # Light security check -- make sure redirect_to isn't garbage.
106             if not redirect_to or '//' in redirect_to or ' ' in redirect_to:
107                 from django.conf import settings
108                 redirect_to = settings.LOGIN_REDIRECT_URL
109             from django.contrib.auth import login
110-            login(request, manipulator.get_user())
111-            request.session.delete_test_cookie()
112+            login(request, form.get_user())           
113+            if request.session.test_cookie_worked():
114+                request.session.delete_test_cookie()
115             return HttpResponseRedirect(redirect_to)
116     else:
117-        errors = {}
118+        form = AuthenticationForm(request=request)
119     request.session.set_test_cookie()
120 
121     if Site._meta.installed:
122@@ -37,7 +37,7 @@
123         current_site = RequestSite(request)
124 
125     return render_to_response(template_name, {
126-        'form': oldforms.FormWrapper(manipulator, request.POST, errors),
127+        'form': form,
128         redirect_field_name: redirect_to,
129         'site_name': current_site.name,
130     }, context_instance=RequestContext(request))
131@@ -68,18 +68,17 @@
132 
133 def password_reset(request, is_admin_site=False, template_name='registration/password_reset_form.html',
134         email_template_name='registration/password_reset_email.html'):
135-    new_data, errors = {}, {}
136-    form = PasswordResetForm()
137     if request.POST:
138-        new_data = request.POST.copy()
139-        errors = form.get_validation_errors(new_data)
140-        if not errors:
141+        form = PasswordResetForm(request.POST)
142+        if form.is_valid():
143             if is_admin_site:
144                 form.save(domain_override=request.META['HTTP_HOST'])
145             else:
146                 form.save(email_template_name=email_template_name)
147             return HttpResponseRedirect('%sdone/' % request.path)
148-    return render_to_response(template_name, {'form': oldforms.FormWrapper(form, new_data, errors)},
149+    else:
150+        form = PasswordResetForm()     
151+    return render_to_response(template_name, {'form': form},
152         context_instance=RequestContext(request))
153 
154 def password_reset_done(request, template_name='registration/password_reset_done.html'):
155@@ -87,14 +86,14 @@
156 
157 def password_change(request, template_name='registration/password_change_form.html'):
158     new_data, errors = {}, {}
159-    form = PasswordChangeForm(request.user)
160-    if request.POST:
161-        new_data = request.POST.copy()
162-        errors = form.get_validation_errors(new_data)
163-        if not errors:
164-            form.save(new_data)
165+    if request.method == 'POST':
166+        form = PasswordChangeForm(request.POST, request.user)
167+        if form.is_valid():
168+            form.save()
169             return HttpResponseRedirect('%sdone/' % request.path)
170-    return render_to_response(template_name, {'form': oldforms.FormWrapper(form, new_data, errors)},
171+    else:
172+        form = PasswordChangeForm(user=request.user)
173+    return render_to_response(template_name, {'form': form},
174         context_instance=RequestContext(request))
175 password_change = login_required(password_change)
176 
177@@ -105,18 +104,14 @@
178     if not request.user.has_perm('auth.change_user'):
179         raise PermissionDenied
180     user = get_object_or_404(User, pk=id)
181-    manipulator = AdminPasswordChangeForm(user)
182     if request.method == 'POST':
183-        new_data = request.POST.copy()
184-        errors = manipulator.get_validation_errors(new_data)
185-        if not errors:
186-            new_user = manipulator.save(new_data)
187+        form = AdminPasswordChangeForm(request.POST, user)
188+        if form.is_valid():
189             msg = _('Password changed successfully.')
190             request.user.message_set.create(message=msg)
191             return HttpResponseRedirect('..')
192     else:
193-        errors = new_data = {}
194-    form = oldforms.FormWrapper(manipulator, new_data, errors)
195+        form = AdminPasswordChangeForm(None,user)
196     return render_to_response('admin/auth/user/change_password.html', {
197         'title': _('Change password: %s') % escape(user.username),
198         'form': form,
199Index: django/contrib/auth/forms.py
200===================================================================
201--- django/contrib/auth/forms.py        (revision 7109)
202+++ django/contrib/auth/forms.py        (working copy)
203@@ -2,38 +2,48 @@
204 from django.contrib.auth import authenticate
205 from django.contrib.sites.models import Site
206 from django.template import Context, loader
207-from django.core import validators
208-from django import oldforms
209+from django import newforms as forms
210 from django.utils.translation import ugettext as _
211+import re
212 
213-class UserCreationForm(oldforms.Manipulator):
214+class UserCreationForm(forms.Form):
215     "A form that creates a user, with no privileges, from the given username and password."
216-    def __init__(self):
217-        self.fields = (
218-            oldforms.TextField(field_name='username', length=30, max_length=30, is_required=True,
219-                validator_list=[validators.isAlphaNumeric, self.isValidUsername]),
220-            oldforms.PasswordField(field_name='password1', length=30, max_length=60, is_required=True),
221-            oldforms.PasswordField(field_name='password2', length=30, max_length=60, is_required=True,
222-                validator_list=[validators.AlwaysMatchesOtherField('password1', _("The two password fields didn't match."))]),
223-        )
224+    username=forms.CharField(label=_("username"), max_length=30, required=True)
225+    password1 = forms.CharField(label=_("password"), max_length=30, required=True, widget=forms.PasswordInput)
226+    password2 = forms.CharField(label=_("password (again)"), max_length=30, required=True, widget=forms.PasswordInput)
227 
228-    def isValidUsername(self, field_data, all_data):
229+    #Following regex and error is borrowed from django.core.validators for backwards compatability for now (including i18n), but in anticipation of them being passed as parameters (or overridden).
230+    username_re = re.compile(r'^\w+$')
231+    username_re_validation_text = "This value must contain only letters, numbers and underscores."
232+
233+    def clean_password2(self):
234+        if self._errors: return
235+        if not self.cleaned_data['password1'] == self.cleaned_data['password2']:   
236+            raise forms.ValidationError, _("The two 'password' fields didn't match.")
237+        return self.cleaned_data['password2']
238+
239+    def clean_username(self):
240+        if not self.username_re.search(self.cleaned_data['username']):
241+            raise forms.ValidationError, _(self.username_re_validation_text)
242         try:
243-            User.objects.get(username=field_data)
244+            user = User.objects.get(username__exact=self.cleaned_data['username'])
245         except User.DoesNotExist:
246-            return
247-        raise validators.ValidationError, _('A user with that username already exists.')
248-
249-    def save(self, new_data):
250+                return self.cleaned_data['username']
251+        raise forms.ValidationError, _('A user with that username already exists.')
252+       
253+    def save(self):
254         "Creates the user."
255-        return User.objects.create_user(new_data['username'], '', new_data['password1'])
256+        return User.objects.create_user(self.cleaned_data['username'], '', self.cleaned_data['password1'])
257 
258-class AuthenticationForm(oldforms.Manipulator):
259+class AuthenticationForm(forms.Form):
260     """
261     Base class for authenticating users. Extend this to get a form that accepts
262     username/password logins.
263     """
264-    def __init__(self, request=None):
265+    username = forms.CharField(label=_("username"), max_length=30, required=True)
266+    password = forms.CharField(label=_("password"), max_length=30, required=True, widget=forms.PasswordInput)
267+   
268+    def __init__(self, request_post=None, request=None):
269         """
270         If request is passed in, the manipulator will validate that cookies are
271         enabled. Note that the request (a HttpRequest object) must have set a
272@@ -41,25 +51,24 @@
273         running this validator.
274         """
275         self.request = request
276-        self.fields = [
277-            oldforms.TextField(field_name="username", length=15, max_length=30, is_required=True,
278-                validator_list=[self.isValidUser, self.hasCookiesEnabled]),
279-            oldforms.PasswordField(field_name="password", length=15, max_length=30, is_required=True),
280-        ]
281         self.user_cache = None
282+        super(AuthenticationForm, self).__init__(request_post)
283 
284-    def hasCookiesEnabled(self, field_data, all_data):
285+    def clean(self):
286+        """
287+        Test that cookies are enabled and that self.username is a valid user with the right password.
288+        """
289+        if self._errors: return
290         if self.request and not self.request.session.test_cookie_worked():
291             raise validators.ValidationError, _("Your Web browser doesn't appear to have cookies enabled. Cookies are required for logging in.")
292-
293-    def isValidUser(self, field_data, all_data):
294-        username = field_data
295-        password = all_data.get('password', None)
296+        username = self.cleaned_data['username']
297+        password = self.cleaned_data['password']
298         self.user_cache = authenticate(username=username, password=password)
299         if self.user_cache is None:
300-            raise validators.ValidationError, _("Please enter a correct username and password. Note that both fields are case-sensitive.")
301+            raise forms.ValidationError, _("Please enter a correct username and password. Note that both fields are case-sensitive.")
302         elif not self.user_cache.is_active:
303-            raise validators.ValidationError, _("This account is inactive.")
304+            raise forms.ValidationError, _("This account is inactive.")
305+        return self.cleaned_data
306 
307     def get_user_id(self):
308         if self.user_cache:
309@@ -69,19 +78,16 @@
310     def get_user(self):
311         return self.user_cache
312 
313-class PasswordResetForm(oldforms.Manipulator):
314+class PasswordResetForm(forms.Form):
315     "A form that lets a user request a password reset"
316-    def __init__(self):
317-        self.fields = (
318-            oldforms.EmailField(field_name="email", length=40, is_required=True,
319-                validator_list=[self.isValidUserEmail]),
320-        )
321-
322-    def isValidUserEmail(self, new_data, all_data):
323+    email = forms.EmailField(label=_("email"), max_length=40, required=True)
324+   
325+    def clean_email(self):
326         "Validates that a user exists with the given e-mail address"
327-        self.users_cache = list(User.objects.filter(email__iexact=new_data))
328+        self.users_cache = list(User.objects.filter(email__iexact=self.cleaned_data['email']))
329         if len(self.users_cache) == 0:
330-            raise validators.ValidationError, _("That e-mail address doesn't have an associated user account. Are you sure you've registered?")
331+            raise forms.ValidationError, _("That e-mail address doesn't have an associated user account. Are you sure you've registered?")
332+        return self.cleaned_data['email']
333 
334     def save(self, domain_override=None, email_template_name='registration/password_reset_email.html'):
335         "Calculates a new password randomly and sends it to the user"
336@@ -106,39 +112,49 @@
337                 }
338             send_mail(_('Password reset on %s') % site_name, t.render(Context(c)), None, [user.email])
339 
340-class PasswordChangeForm(oldforms.Manipulator):
341-    "A form that lets a user change his password."
342-    def __init__(self, user):
343+class PasswordChangeForm(forms.Form):
344+    "A form that lets a user change his or her password."
345+    old_password = forms.CharField(label=_("old password"), max_length=30, required=True, widget=forms.PasswordInput)
346+    new_password1 = forms.CharField(label=_("new password"), max_length=30, required=True, widget=forms.PasswordInput)
347+    new_password2 = forms.CharField(label=_("new password again"), max_length=30, required=True, widget=forms.PasswordInput)
348+
349+    def __init__(self, request_post=None, user=None):
350         self.user = user
351-        self.fields = (
352-            oldforms.PasswordField(field_name="old_password", length=30, max_length=30, is_required=True,
353-                validator_list=[self.isValidOldPassword]),
354-            oldforms.PasswordField(field_name="new_password1", length=30, max_length=30, is_required=True,
355-                validator_list=[validators.AlwaysMatchesOtherField('new_password2', _("The two 'new password' fields didn't match."))]),
356-            oldforms.PasswordField(field_name="new_password2", length=30, max_length=30, is_required=True),
357-        )
358+        super(PasswordChangeForm,self).__init__(request_post)
359+       
360+    def clean_new_password2(self):
361+        if self._errors: return
362+        if not self.cleaned_data['new_password1'] == self.cleaned_data['new_password2']:   
363+            raise forms.ValidationError, _("The two 'new password' fields didn't match.")
364+        return self.cleaned_data['new_password2']
365 
366-    def isValidOldPassword(self, new_data, all_data):
367+    def clean_old_password(self):
368         "Validates that the old_password field is correct."
369-        if not self.user.check_password(new_data):
370-            raise validators.ValidationError, _("Your old password was entered incorrectly. Please enter it again.")
371+        if not self.user.check_password(self.cleaned_data['old_password']):
372+            raise forms.ValidationError, _("Your old password was entered incorrectly. Please enter it again.")
373+        return self.cleaned_data['old_password']
374 
375-    def save(self, new_data):
376+    def save(self):
377         "Saves the new password."
378-        self.user.set_password(new_data['new_password1'])
379+        self.user.set_password(self.cleaned_data['new_password1'])
380         self.user.save()
381 
382-class AdminPasswordChangeForm(oldforms.Manipulator):
383-    "A form used to change the password of a user in the admin interface."
384-    def __init__(self, user):
385+class AdminPasswordChangeForm(forms.Form):
386+    "A form used to change the password of a user in the admin interface - it is not necessary to know the old password."
387+    password1 = forms.CharField(label=_("new password"), max_length=30, required=True, widget=forms.PasswordInput)
388+    password2 = forms.CharField(label=_("new password again"), max_length=30, required=True, widget=forms.PasswordInput)
389+
390+    def __init__(self, request_post=None, user=None):
391         self.user = user
392-        self.fields = (
393-            oldforms.PasswordField(field_name='password1', length=30, max_length=60, is_required=True),
394-            oldforms.PasswordField(field_name='password2', length=30, max_length=60, is_required=True,
395-                validator_list=[validators.AlwaysMatchesOtherField('password1', _("The two password fields didn't match."))]),
396-        )
397+        super(AdminPasswordChangeForm,self).__init__(request_post)
398 
399-    def save(self, new_data):
400+    def clean(self):
401+        if self._errors: return
402+        if self.cleaned_data['password1'] == self.cleaned_data['password2']:   
403+            return self.cleaned_data
404+        raise forms.ValidationError, _("The two 'new password' fields didn't match.")
405+
406+    def save(self):
407         "Saves the new password."
408-        self.user.set_password(new_data['password1'])
409+        self.user.set_password(self.cleaned_data['password1'])
410         self.user.save()
411Index: AUTHORS
412===================================================================
413--- AUTHORS     (revision 7109)
414+++ AUTHORS     (working copy)
415@@ -335,6 +335,7 @@
416     tstromberg@google.com
417     Makoto Tsuyuki <mtsuyuki@gmail.com>
418     tt@gurgle.no
419+    Greg Turner <http://gregturner.org>
420     Amit Upadhyay
421     Geert Vanderkelen
422     I.S. van Oostveen <v.oostveen@idca.nl>