]> git.openstreetmap.org Git - osqa.git/blob - forum/utils/forms.py
Fixes a bug happening when processing an user reputation more than once in the same...
[osqa.git] / forum / utils / forms.py
1 from django import forms
2 import re
3 from django.utils.translation import ugettext as _
4 from django.utils.safestring import mark_safe
5 from forum import settings
6 from django.http import str_to_unicode
7 from forum.models import User
8 import urllib
9
10 DEFAULT_NEXT = '/' + getattr(settings, 'FORUM_SCRIPT_ALIAS')
11 def clean_next(next):
12     if next is None:
13         return DEFAULT_NEXT
14     next = str_to_unicode(urllib.unquote(next), 'utf-8')
15     next = next.strip()
16     if next.startswith('/'):
17         return next
18     return DEFAULT_NEXT
19
20 def get_next_url(request):
21     return clean_next(request.REQUEST.get('next'))
22
23 class StrippedNonEmptyCharField(forms.CharField):
24     def clean(self,value):
25         value = value.strip()
26         if self.required and value == '':
27             raise forms.ValidationError(_('this field is required'))
28         return value
29
30 class NextUrlField(forms.CharField):
31     def __init__(self):
32         super(NextUrlField,self).__init__(max_length = 255,widget = forms.HiddenInput(),required = False)
33     def clean(self,value):
34         return clean_next(value)
35
36 login_form_widget_attrs = { 'class': 'required login' }
37 username_re = re.compile(r'^[\w\s ]+$', re.UNICODE)
38
39 class UserNameField(StrippedNonEmptyCharField):
40     def __init__(self,db_model=User, db_field='username', must_exist=False,skip_clean=False,label=_('choose a username'),**kw):
41         self.must_exist = must_exist
42         self.skip_clean = skip_clean
43         self.db_model = db_model 
44         self.db_field = db_field
45         error_messages={'required':_('user name is required'),
46                         'taken':_('sorry, this name is taken, please choose another'),
47                         'forbidden':_('sorry, this name is not allowed, please choose another'),
48                         'missing':_('sorry, there is no user with this name'),
49                         'multiple-taken':_('sorry, we have a serious error - user name is taken by several users'),
50                         'invalid':_('user name can only consist of letters, empty space and underscore'),
51                         'toshort':_('user name is to short, please use at least %d characters') % settings.MIN_USERNAME_LENGTH
52                     }
53         if 'error_messages' in kw:
54             error_messages.update(kw['error_messages'])
55             del kw['error_messages']
56         super(UserNameField,self).__init__(max_length=30,
57                 widget=forms.TextInput(attrs=login_form_widget_attrs),
58                 label=label,
59                 error_messages=error_messages,
60                 **kw
61                 )
62
63     def clean(self,username):
64         """ validate username """
65         if self.skip_clean == True:
66             return username
67         if hasattr(self, 'user_instance') and isinstance(self.user_instance, User):
68             if username == self.user_instance.username:
69                 return username
70         try:
71             username = super(UserNameField, self).clean(username)
72         except forms.ValidationError:
73             raise forms.ValidationError(self.error_messages['required'])
74         if len(username) < settings.MIN_USERNAME_LENGTH:
75             raise forms.ValidationError(self.error_messages['toshort'])
76         if self.required and not username_re.match(username):
77             raise forms.ValidationError(self.error_messages['invalid'])
78         if username in settings.RESERVED_USERNAMES:
79             raise forms.ValidationError(self.error_messages['forbidden'])
80         try:
81             user = self.db_model.objects.get(
82                     **{'%s' % self.db_field : username}
83             )
84             if user:
85                 if self.must_exist:
86                     return username
87                 else:
88                     raise forms.ValidationError(self.error_messages['taken'])
89         except self.db_model.DoesNotExist:
90             if self.must_exist:
91                 raise forms.ValidationError(self.error_messages['missing'])
92             else:
93                 return username
94         except self.db_model.MultipleObjectsReturned:
95             raise forms.ValidationError(self.error_messages['multiple-taken'])
96
97 class UserEmailField(forms.EmailField):
98     def __init__(self,skip_clean=False,**kw):
99         self.skip_clean = skip_clean
100         super(UserEmailField,self).__init__(widget=forms.TextInput(attrs=dict(login_form_widget_attrs,
101             maxlength=200)), label=mark_safe(_('your email address')),
102             error_messages={'required':_('email address is required'),
103                             'invalid':_('please enter a valid email address'),
104                             'taken':_('this email is already used by someone else, please choose another'),
105                             },
106             **kw
107             )
108
109     def clean(self,email):
110         """ validate if email exist in database
111         from legacy register
112         return: raise error if it exist """
113         email = super(UserEmailField,self).clean(email.strip())
114         if self.skip_clean:
115             return email
116         if settings.EMAIL_UNIQUE == True:
117             try:
118                 user = User.objects.get(email = email)
119                 raise forms.ValidationError(self.error_messages['taken'])
120             except User.DoesNotExist:
121                 return email
122             except User.MultipleObjectsReturned:
123                 raise forms.ValidationError(self.error_messages['taken'])
124         else:
125             return email 
126
127 class SetPasswordForm(forms.Form):
128     password1 = forms.CharField(widget=forms.PasswordInput(attrs=login_form_widget_attrs),
129                                 label=_('choose password'),
130                                 error_messages={'required':_('password is required')},
131                                 )
132     password2 = forms.CharField(widget=forms.PasswordInput(attrs=login_form_widget_attrs),
133                                 label=mark_safe(_('retype password')),
134                                 error_messages={'required':_('please, retype your password'),
135                                                 'nomatch':_('sorry, entered passwords did not match, please try again')},
136                                 )
137
138     def __init__(self, data=None, user=None, *args, **kwargs):
139         super(SetPasswordForm, self).__init__(data, *args, **kwargs)
140
141     def clean_password2(self):
142         """
143         Validates that the two password inputs match.
144         
145         """
146         if 'password1' in self.cleaned_data:
147             if self.cleaned_data['password1'] == self.cleaned_data['password2']:
148                 self.password = self.cleaned_data['password2']
149                 self.cleaned_data['password'] = self.cleaned_data['password2']
150                 return self.cleaned_data['password2']
151             else:
152                 del self.cleaned_data['password2']
153                 raise forms.ValidationError(self.fields['password2'].error_messages['nomatch'])
154         else:
155             return self.cleaned_data['password2']
156