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