##// END OF EJS Templates
Added validation for uniq email address
marcink -
r475:9dd38344 celery
parent child Browse files
Show More
@@ -1,334 +1,347 b''
1 """ this is forms validation classes
1 """ this is forms validation classes
2 http://formencode.org/module-formencode.validators.html
2 http://formencode.org/module-formencode.validators.html
3 for list off all availible validators
3 for list off all availible validators
4
4
5 we can create our own validators
5 we can create our own validators
6
6
7 The table below outlines the options which can be used in a schema in addition to the validators themselves
7 The table below outlines the options which can be used in a schema in addition to the validators themselves
8 pre_validators [] These validators will be applied before the schema
8 pre_validators [] These validators will be applied before the schema
9 chained_validators [] These validators will be applied after the schema
9 chained_validators [] These validators will be applied after the schema
10 allow_extra_fields False If True, then it is not an error when keys that aren't associated with a validator are present
10 allow_extra_fields False If True, then it is not an error when keys that aren't associated with a validator are present
11 filter_extra_fields False If True, then keys that aren't associated with a validator are removed
11 filter_extra_fields False If True, then keys that aren't associated with a validator are removed
12 if_key_missing NoDefault If this is given, then any keys that aren't available but are expected will be replaced with this value (and then validated). This does not override a present .if_missing attribute on validators. NoDefault is a special FormEncode class to mean that no default values has been specified and therefore missing keys shouldn't take a default value.
12 if_key_missing NoDefault If this is given, then any keys that aren't available but are expected will be replaced with this value (and then validated). This does not override a present .if_missing attribute on validators. NoDefault is a special FormEncode class to mean that no default values has been specified and therefore missing keys shouldn't take a default value.
13 ignore_key_missing False If True, then missing keys will be missing in the result, if the validator doesn't have .if_missing on it already
13 ignore_key_missing False If True, then missing keys will be missing in the result, if the validator doesn't have .if_missing on it already
14
14
15
15
16 <name> = formencode.validators.<name of validator>
16 <name> = formencode.validators.<name of validator>
17 <name> must equal form name
17 <name> must equal form name
18 list=[1,2,3,4,5]
18 list=[1,2,3,4,5]
19 for SELECT use formencode.All(OneOf(list), Int())
19 for SELECT use formencode.All(OneOf(list), Int())
20
20
21 """
21 """
22 from formencode import All
22 from formencode import All
23 from formencode.validators import UnicodeString, OneOf, Int, Number, Regex, \
23 from formencode.validators import UnicodeString, OneOf, Int, Number, Regex, \
24 Email, Bool, StringBoolean
24 Email, Bool, StringBoolean
25 from pylons import session
25 from pylons import session
26 from pylons.i18n.translation import _
26 from pylons.i18n.translation import _
27 from pylons_app.lib.auth import check_password, get_crypt_password
27 from pylons_app.lib.auth import check_password, get_crypt_password
28 from pylons_app.model import meta
28 from pylons_app.model import meta
29 from pylons_app.model.user_model import UserModel
29 from pylons_app.model.user_model import UserModel
30 from pylons_app.model.db import User, Repository
30 from pylons_app.model.db import User, Repository
31 from sqlalchemy.exc import OperationalError
31 from sqlalchemy.exc import OperationalError
32 from sqlalchemy.orm.exc import NoResultFound, MultipleResultsFound
32 from sqlalchemy.orm.exc import NoResultFound, MultipleResultsFound
33 from webhelpers.pylonslib.secure_form import authentication_token
33 from webhelpers.pylonslib.secure_form import authentication_token
34 import formencode
34 import formencode
35 import logging
35 import logging
36 import os
36 import os
37 import pylons_app.lib.helpers as h
37 import pylons_app.lib.helpers as h
38 log = logging.getLogger(__name__)
38 log = logging.getLogger(__name__)
39
39
40
40
41 #this is needed to translate the messages using _() in validators
41 #this is needed to translate the messages using _() in validators
42 class State_obj(object):
42 class State_obj(object):
43 _ = staticmethod(_)
43 _ = staticmethod(_)
44
44
45 #===============================================================================
45 #===============================================================================
46 # VALIDATORS
46 # VALIDATORS
47 #===============================================================================
47 #===============================================================================
48 class ValidAuthToken(formencode.validators.FancyValidator):
48 class ValidAuthToken(formencode.validators.FancyValidator):
49 messages = {'invalid_token':_('Token mismatch')}
49 messages = {'invalid_token':_('Token mismatch')}
50
50
51 def validate_python(self, value, state):
51 def validate_python(self, value, state):
52
52
53 if value != authentication_token():
53 if value != authentication_token():
54 raise formencode.Invalid(self.message('invalid_token', state,
54 raise formencode.Invalid(self.message('invalid_token', state,
55 search_number=value), value, state)
55 search_number=value), value, state)
56
56
57 def ValidUsername(edit, old_data):
57 def ValidUsername(edit, old_data):
58 class _ValidUsername(formencode.validators.FancyValidator):
58 class _ValidUsername(formencode.validators.FancyValidator):
59
59
60 def validate_python(self, value, state):
60 def validate_python(self, value, state):
61 if value in ['default', 'new_user']:
61 if value in ['default', 'new_user']:
62 raise formencode.Invalid(_('Invalid username'), value, state)
62 raise formencode.Invalid(_('Invalid username'), value, state)
63 #check if user is uniq
63 #check if user is uniq
64 sa = meta.Session
64 sa = meta.Session
65 old_un = None
65 old_un = None
66 if edit:
66 if edit:
67 old_un = sa.query(User).get(old_data.get('user_id')).username
67 old_un = sa.query(User).get(old_data.get('user_id')).username
68
68
69 if old_un != value or not edit:
69 if old_un != value or not edit:
70 if sa.query(User).filter(User.username == value).scalar():
70 if sa.query(User).filter(User.username == value).scalar():
71 raise formencode.Invalid(_('This username already exists') ,
71 raise formencode.Invalid(_('This username already exists') ,
72 value, state)
72 value, state)
73 meta.Session.remove()
73 meta.Session.remove()
74
74
75 return _ValidUsername
75 return _ValidUsername
76
76
77 class ValidPassword(formencode.validators.FancyValidator):
77 class ValidPassword(formencode.validators.FancyValidator):
78
78
79 def to_python(self, value, state):
79 def to_python(self, value, state):
80 if value:
80 if value:
81 return get_crypt_password(value)
81 return get_crypt_password(value)
82
82
83 class ValidAuth(formencode.validators.FancyValidator):
83 class ValidAuth(formencode.validators.FancyValidator):
84 messages = {
84 messages = {
85 'invalid_password':_('invalid password'),
85 'invalid_password':_('invalid password'),
86 'invalid_login':_('invalid user name'),
86 'invalid_login':_('invalid user name'),
87 'disabled_account':_('Your acccount is disabled')
87 'disabled_account':_('Your acccount is disabled')
88
88
89 }
89 }
90 #error mapping
90 #error mapping
91 e_dict = {'username':messages['invalid_login'],
91 e_dict = {'username':messages['invalid_login'],
92 'password':messages['invalid_password']}
92 'password':messages['invalid_password']}
93 e_dict_disable = {'username':messages['disabled_account']}
93 e_dict_disable = {'username':messages['disabled_account']}
94
94
95 def validate_python(self, value, state):
95 def validate_python(self, value, state):
96 password = value['password']
96 password = value['password']
97 username = value['username']
97 username = value['username']
98 user = UserModel().get_user_by_name(username)
98 user = UserModel().get_user_by_name(username)
99 if user is None:
99 if user is None:
100 raise formencode.Invalid(self.message('invalid_password',
100 raise formencode.Invalid(self.message('invalid_password',
101 state=State_obj), value, state,
101 state=State_obj), value, state,
102 error_dict=self.e_dict)
102 error_dict=self.e_dict)
103 if user:
103 if user:
104 if user.active:
104 if user.active:
105 if user.username == username and check_password(password,
105 if user.username == username and check_password(password,
106 user.password):
106 user.password):
107 return value
107 return value
108 else:
108 else:
109 log.warning('user %s not authenticated', username)
109 log.warning('user %s not authenticated', username)
110 raise formencode.Invalid(self.message('invalid_password',
110 raise formencode.Invalid(self.message('invalid_password',
111 state=State_obj), value, state,
111 state=State_obj), value, state,
112 error_dict=self.e_dict)
112 error_dict=self.e_dict)
113 else:
113 else:
114 log.warning('user %s is disabled', username)
114 log.warning('user %s is disabled', username)
115 raise formencode.Invalid(self.message('disabled_account',
115 raise formencode.Invalid(self.message('disabled_account',
116 state=State_obj),
116 state=State_obj),
117 value, state,
117 value, state,
118 error_dict=self.e_dict_disable)
118 error_dict=self.e_dict_disable)
119
119
120 class ValidRepoUser(formencode.validators.FancyValidator):
120 class ValidRepoUser(formencode.validators.FancyValidator):
121
121
122 def to_python(self, value, state):
122 def to_python(self, value, state):
123 try:
123 try:
124 self.user_db = meta.Session.query(User)\
124 self.user_db = meta.Session.query(User)\
125 .filter(User.active == True)\
125 .filter(User.active == True)\
126 .filter(User.username == value).one()
126 .filter(User.username == value).one()
127 except Exception:
127 except Exception:
128 raise formencode.Invalid(_('This username is not valid'),
128 raise formencode.Invalid(_('This username is not valid'),
129 value, state)
129 value, state)
130 finally:
130 finally:
131 meta.Session.remove()
131 meta.Session.remove()
132
132
133 return self.user_db.user_id
133 return self.user_db.user_id
134
134
135 def ValidRepoName(edit, old_data):
135 def ValidRepoName(edit, old_data):
136 class _ValidRepoName(formencode.validators.FancyValidator):
136 class _ValidRepoName(formencode.validators.FancyValidator):
137
137
138 def to_python(self, value, state):
138 def to_python(self, value, state):
139 slug = h.repo_name_slug(value)
139 slug = h.repo_name_slug(value)
140 if slug in ['_admin']:
140 if slug in ['_admin']:
141 raise formencode.Invalid(_('This repository name is disallowed'),
141 raise formencode.Invalid(_('This repository name is disallowed'),
142 value, state)
142 value, state)
143 if old_data.get('repo_name') != value or not edit:
143 if old_data.get('repo_name') != value or not edit:
144 sa = meta.Session
144 sa = meta.Session
145 if sa.query(Repository).filter(Repository.repo_name == slug).scalar():
145 if sa.query(Repository).filter(Repository.repo_name == slug).scalar():
146 raise formencode.Invalid(_('This repository already exists') ,
146 raise formencode.Invalid(_('This repository already exists') ,
147 value, state)
147 value, state)
148 meta.Session.remove()
148 meta.Session.remove()
149 return slug
149 return slug
150
150
151
151
152 return _ValidRepoName
152 return _ValidRepoName
153
153
154 class ValidPerms(formencode.validators.FancyValidator):
154 class ValidPerms(formencode.validators.FancyValidator):
155 messages = {'perm_new_user_name':_('This username is not valid')}
155 messages = {'perm_new_user_name':_('This username is not valid')}
156
156
157 def to_python(self, value, state):
157 def to_python(self, value, state):
158 perms_update = []
158 perms_update = []
159 perms_new = []
159 perms_new = []
160 #build a list of permission to update and new permission to create
160 #build a list of permission to update and new permission to create
161 for k, v in value.items():
161 for k, v in value.items():
162 if k.startswith('perm_'):
162 if k.startswith('perm_'):
163 if k.startswith('perm_new_user'):
163 if k.startswith('perm_new_user'):
164 new_perm = value.get('perm_new_user', False)
164 new_perm = value.get('perm_new_user', False)
165 new_user = value.get('perm_new_user_name', False)
165 new_user = value.get('perm_new_user_name', False)
166 if new_user and new_perm:
166 if new_user and new_perm:
167 if (new_user, new_perm) not in perms_new:
167 if (new_user, new_perm) not in perms_new:
168 perms_new.append((new_user, new_perm))
168 perms_new.append((new_user, new_perm))
169 else:
169 else:
170 usr = k[5:]
170 usr = k[5:]
171 if usr == 'default':
171 if usr == 'default':
172 if value['private']:
172 if value['private']:
173 #set none for default when updating to private repo
173 #set none for default when updating to private repo
174 v = 'repository.none'
174 v = 'repository.none'
175 perms_update.append((usr, v))
175 perms_update.append((usr, v))
176 value['perms_updates'] = perms_update
176 value['perms_updates'] = perms_update
177 value['perms_new'] = perms_new
177 value['perms_new'] = perms_new
178 sa = meta.Session
178 sa = meta.Session
179 for k, v in perms_new:
179 for k, v in perms_new:
180 try:
180 try:
181 self.user_db = sa.query(User)\
181 self.user_db = sa.query(User)\
182 .filter(User.active == True)\
182 .filter(User.active == True)\
183 .filter(User.username == k).one()
183 .filter(User.username == k).one()
184 except Exception:
184 except Exception:
185 msg = self.message('perm_new_user_name',
185 msg = self.message('perm_new_user_name',
186 state=State_obj)
186 state=State_obj)
187 raise formencode.Invalid(msg, value, state, error_dict={'perm_new_user_name':msg})
187 raise formencode.Invalid(msg, value, state, error_dict={'perm_new_user_name':msg})
188 return value
188 return value
189
189
190 class ValidSettings(formencode.validators.FancyValidator):
190 class ValidSettings(formencode.validators.FancyValidator):
191
191
192 def to_python(self, value, state):
192 def to_python(self, value, state):
193 #settings form can't edit user
193 #settings form can't edit user
194 if value.has_key('user'):
194 if value.has_key('user'):
195 del['value']['user']
195 del['value']['user']
196
196
197 return value
197 return value
198
198
199 class ValidPath(formencode.validators.FancyValidator):
199 class ValidPath(formencode.validators.FancyValidator):
200 def to_python(self, value, state):
200 def to_python(self, value, state):
201 isdir = os.path.isdir(value.replace('*', ''))
201 isdir = os.path.isdir(value.replace('*', ''))
202 if (value.endswith('/*') or value.endswith('/**')) and isdir:
202 if (value.endswith('/*') or value.endswith('/**')) and isdir:
203 return value
203 return value
204 elif not isdir:
204 elif not isdir:
205 msg = _('This is not a valid path')
205 msg = _('This is not a valid path')
206 else:
206 else:
207 msg = _('You need to specify * or ** at the end of path (ie. /tmp/*)')
207 msg = _('You need to specify * or ** at the end of path (ie. /tmp/*)')
208
208
209 raise formencode.Invalid(msg, value, state,
209 raise formencode.Invalid(msg, value, state,
210 error_dict={'paths_root_path':msg})
210 error_dict={'paths_root_path':msg})
211
211
212 class UniqSystemEmail(formencode.validators.FancyValidator):
213 def to_python(self, value, state):
214 sa = meta.Session
215 try:
216 user = sa.query(User).filter(User.email == value).scalar()
217 if user:
218 raise formencode.Invalid(_("That e-mail address is already taken") ,
219 value, state)
220 finally:
221 meta.Session.remove()
222
223 return value
224
212 class ValidSystemEmail(formencode.validators.FancyValidator):
225 class ValidSystemEmail(formencode.validators.FancyValidator):
213 def to_python(self, value, state):
226 def to_python(self, value, state):
214 sa = meta.Session
227 sa = meta.Session
215 try:
228 try:
216 user = sa.query(User).filter(User.email == value).scalar()
229 user = sa.query(User).filter(User.email == value).scalar()
217 if user is None:
230 if user is None:
218 raise formencode.Invalid(_("That e-mail address doesn't exist.") ,
231 raise formencode.Invalid(_("That e-mail address doesn't exist.") ,
219 value, state)
232 value, state)
220 finally:
233 finally:
221 meta.Session.remove()
234 meta.Session.remove()
222
235
223 return value
236 return value
224
237
225 #===============================================================================
238 #===============================================================================
226 # FORMS
239 # FORMS
227 #===============================================================================
240 #===============================================================================
228 class LoginForm(formencode.Schema):
241 class LoginForm(formencode.Schema):
229 allow_extra_fields = True
242 allow_extra_fields = True
230 filter_extra_fields = True
243 filter_extra_fields = True
231 username = UnicodeString(
244 username = UnicodeString(
232 strip=True,
245 strip=True,
233 min=3,
246 min=3,
234 not_empty=True,
247 not_empty=True,
235 messages={
248 messages={
236 'empty':_('Please enter a login'),
249 'empty':_('Please enter a login'),
237 'tooShort':_('Enter a value %(min)i characters long or more')}
250 'tooShort':_('Enter a value %(min)i characters long or more')}
238 )
251 )
239
252
240 password = UnicodeString(
253 password = UnicodeString(
241 strip=True,
254 strip=True,
242 min=3,
255 min=3,
243 not_empty=True,
256 not_empty=True,
244 messages={
257 messages={
245 'empty':_('Please enter a password'),
258 'empty':_('Please enter a password'),
246 'tooShort':_('Enter a value %(min)i characters long or more')}
259 'tooShort':_('Enter a value %(min)i characters long or more')}
247 )
260 )
248
261
249
262
250 #chained validators have access to all data
263 #chained validators have access to all data
251 chained_validators = [ValidAuth]
264 chained_validators = [ValidAuth]
252
265
253 def UserForm(edit=False, old_data={}):
266 def UserForm(edit=False, old_data={}):
254 class _UserForm(formencode.Schema):
267 class _UserForm(formencode.Schema):
255 allow_extra_fields = True
268 allow_extra_fields = True
256 filter_extra_fields = True
269 filter_extra_fields = True
257 username = All(UnicodeString(strip=True, min=3, not_empty=True), ValidUsername(edit, old_data))
270 username = All(UnicodeString(strip=True, min=3, not_empty=True), ValidUsername(edit, old_data))
258 if edit:
271 if edit:
259 new_password = All(UnicodeString(strip=True, min=3, not_empty=False), ValidPassword)
272 new_password = All(UnicodeString(strip=True, min=3, not_empty=False), ValidPassword)
260 admin = StringBoolean(if_missing=False)
273 admin = StringBoolean(if_missing=False)
261 else:
274 else:
262 password = All(UnicodeString(strip=True, min=8, not_empty=True), ValidPassword)
275 password = All(UnicodeString(strip=True, min=8, not_empty=True), ValidPassword)
263 active = StringBoolean(if_missing=False)
276 active = StringBoolean(if_missing=False)
264 name = UnicodeString(strip=True, min=3, not_empty=True)
277 name = UnicodeString(strip=True, min=3, not_empty=True)
265 lastname = UnicodeString(strip=True, min=3, not_empty=True)
278 lastname = UnicodeString(strip=True, min=3, not_empty=True)
266 email = Email(not_empty=True)
279 email = All(Email(not_empty=True), UniqSystemEmail())
267
280
268 return _UserForm
281 return _UserForm
269
282
270 RegisterForm = UserForm
283 RegisterForm = UserForm
271
284
272 def PasswordResetForm():
285 def PasswordResetForm():
273 class _PasswordResetForm(formencode.Schema):
286 class _PasswordResetForm(formencode.Schema):
274 allow_extra_fields = True
287 allow_extra_fields = True
275 filter_extra_fields = True
288 filter_extra_fields = True
276 email = All(ValidSystemEmail(), Email(not_empty=True))
289 email = All(ValidSystemEmail(), Email(not_empty=True))
277 return _PasswordResetForm
290 return _PasswordResetForm
278
291
279 def RepoForm(edit=False, old_data={}):
292 def RepoForm(edit=False, old_data={}):
280 class _RepoForm(formencode.Schema):
293 class _RepoForm(formencode.Schema):
281 allow_extra_fields = True
294 allow_extra_fields = True
282 filter_extra_fields = False
295 filter_extra_fields = False
283 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True), ValidRepoName(edit, old_data))
296 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True), ValidRepoName(edit, old_data))
284 description = UnicodeString(strip=True, min=3, not_empty=True)
297 description = UnicodeString(strip=True, min=3, not_empty=True)
285 private = StringBoolean(if_missing=False)
298 private = StringBoolean(if_missing=False)
286
299
287 if edit:
300 if edit:
288 user = All(Int(not_empty=True), ValidRepoUser)
301 user = All(Int(not_empty=True), ValidRepoUser)
289
302
290 chained_validators = [ValidPerms]
303 chained_validators = [ValidPerms]
291 return _RepoForm
304 return _RepoForm
292
305
293 def RepoSettingsForm(edit=False, old_data={}):
306 def RepoSettingsForm(edit=False, old_data={}):
294 class _RepoForm(formencode.Schema):
307 class _RepoForm(formencode.Schema):
295 allow_extra_fields = True
308 allow_extra_fields = True
296 filter_extra_fields = False
309 filter_extra_fields = False
297 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True), ValidRepoName(edit, old_data))
310 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True), ValidRepoName(edit, old_data))
298 description = UnicodeString(strip=True, min=3, not_empty=True)
311 description = UnicodeString(strip=True, min=3, not_empty=True)
299 private = StringBoolean(if_missing=False)
312 private = StringBoolean(if_missing=False)
300
313
301 chained_validators = [ValidPerms, ValidSettings]
314 chained_validators = [ValidPerms, ValidSettings]
302 return _RepoForm
315 return _RepoForm
303
316
304
317
305 def ApplicationSettingsForm():
318 def ApplicationSettingsForm():
306 class _ApplicationSettingsForm(formencode.Schema):
319 class _ApplicationSettingsForm(formencode.Schema):
307 allow_extra_fields = True
320 allow_extra_fields = True
308 filter_extra_fields = False
321 filter_extra_fields = False
309 hg_app_title = UnicodeString(strip=True, min=3, not_empty=True)
322 hg_app_title = UnicodeString(strip=True, min=3, not_empty=True)
310 hg_app_realm = UnicodeString(strip=True, min=3, not_empty=True)
323 hg_app_realm = UnicodeString(strip=True, min=3, not_empty=True)
311
324
312 return _ApplicationSettingsForm
325 return _ApplicationSettingsForm
313
326
314 def ApplicationUiSettingsForm():
327 def ApplicationUiSettingsForm():
315 class _ApplicationUiSettingsForm(formencode.Schema):
328 class _ApplicationUiSettingsForm(formencode.Schema):
316 allow_extra_fields = True
329 allow_extra_fields = True
317 filter_extra_fields = False
330 filter_extra_fields = False
318 web_push_ssl = OneOf(['true', 'false'], if_missing='false')
331 web_push_ssl = OneOf(['true', 'false'], if_missing='false')
319 paths_root_path = All(ValidPath(), UnicodeString(strip=True, min=3, not_empty=True))
332 paths_root_path = All(ValidPath(), UnicodeString(strip=True, min=3, not_empty=True))
320 hooks_changegroup_update = OneOf(['True', 'False'], if_missing=False)
333 hooks_changegroup_update = OneOf(['True', 'False'], if_missing=False)
321 hooks_changegroup_repo_size = OneOf(['True', 'False'], if_missing=False)
334 hooks_changegroup_repo_size = OneOf(['True', 'False'], if_missing=False)
322
335
323 return _ApplicationUiSettingsForm
336 return _ApplicationUiSettingsForm
324
337
325 def DefaultPermissionsForm(perms_choices, register_choices, create_choices):
338 def DefaultPermissionsForm(perms_choices, register_choices, create_choices):
326 class _DefaultPermissionsForm(formencode.Schema):
339 class _DefaultPermissionsForm(formencode.Schema):
327 allow_extra_fields = True
340 allow_extra_fields = True
328 filter_extra_fields = True
341 filter_extra_fields = True
329 overwrite_default = OneOf(['true', 'false'], if_missing='false')
342 overwrite_default = OneOf(['true', 'false'], if_missing='false')
330 default_perm = OneOf(perms_choices)
343 default_perm = OneOf(perms_choices)
331 default_register = OneOf(register_choices)
344 default_register = OneOf(register_choices)
332 default_create = OneOf(create_choices)
345 default_create = OneOf(create_choices)
333
346
334 return _DefaultPermissionsForm
347 return _DefaultPermissionsForm
General Comments 0
You need to be logged in to leave comments. Login now