##// END OF EJS Templates
added test for username and email case senstitive validators,...
marcink -
r745:c366b237 beta
parent child Browse files
Show More
@@ -1,459 +1,459 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 rhodecode.lib.auth import authfunc, get_crypt_password
27 from rhodecode.lib.auth import authfunc, get_crypt_password
28 from rhodecode.lib.exceptions import LdapImportError
28 from rhodecode.lib.exceptions import LdapImportError
29 from rhodecode.model import meta
29 from rhodecode.model import meta
30 from rhodecode.model.user import UserModel
30 from rhodecode.model.user import UserModel
31 from rhodecode.model.repo import RepoModel
31 from rhodecode.model.repo import RepoModel
32 from rhodecode.model.db import User
32 from rhodecode.model.db import User
33 from webhelpers.pylonslib.secure_form import authentication_token
33 from webhelpers.pylonslib.secure_form import authentication_token
34 from rhodecode import BACKENDS
34 from rhodecode import BACKENDS
35 import formencode
35 import formencode
36 import logging
36 import logging
37 import os
37 import os
38 import re
38 import re
39 import rhodecode.lib.helpers as h
39 import rhodecode.lib.helpers as h
40
40
41 log = logging.getLogger(__name__)
41 log = logging.getLogger(__name__)
42
42
43 #this is needed to translate the messages using _() in validators
43 #this is needed to translate the messages using _() in validators
44 class State_obj(object):
44 class State_obj(object):
45 _ = staticmethod(_)
45 _ = staticmethod(_)
46
46
47 #===============================================================================
47 #===============================================================================
48 # VALIDATORS
48 # VALIDATORS
49 #===============================================================================
49 #===============================================================================
50 class ValidAuthToken(formencode.validators.FancyValidator):
50 class ValidAuthToken(formencode.validators.FancyValidator):
51 messages = {'invalid_token':_('Token mismatch')}
51 messages = {'invalid_token':_('Token mismatch')}
52
52
53 def validate_python(self, value, state):
53 def validate_python(self, value, state):
54
54
55 if value != authentication_token():
55 if value != authentication_token():
56 raise formencode.Invalid(self.message('invalid_token', state,
56 raise formencode.Invalid(self.message('invalid_token', state,
57 search_number=value), value, state)
57 search_number=value), value, state)
58
58
59 def ValidUsername(edit, old_data):
59 def ValidUsername(edit, old_data):
60 class _ValidUsername(formencode.validators.FancyValidator):
60 class _ValidUsername(formencode.validators.FancyValidator):
61
61
62 def validate_python(self, value, state):
62 def validate_python(self, value, state):
63 if value in ['default', 'new_user']:
63 if value in ['default', 'new_user']:
64 raise formencode.Invalid(_('Invalid username'), value, state)
64 raise formencode.Invalid(_('Invalid username'), value, state)
65 #check if user is unique
65 #check if user is unique
66 old_un = None
66 old_un = None
67 if edit:
67 if edit:
68 old_un = UserModel().get(old_data.get('user_id')).username
68 old_un = UserModel().get(old_data.get('user_id')).username
69
69
70 if old_un != value or not edit:
70 if old_un != value or not edit:
71 if UserModel().get_by_username(value, cache=False,
71 if UserModel().get_by_username(value, cache=False,
72 case_insensitive=True):
72 case_insensitive=True):
73 raise formencode.Invalid(_('This username already exists') ,
73 raise formencode.Invalid(_('This username already exists') ,
74 value, state)
74 value, state)
75
75
76
76
77 if re.match(r'^[a-zA-Z0-9]{1}[a-zA-Z0-9\-]+$', value) is None:
77 if re.match(r'^[a-zA-Z0-9]{1}[a-zA-Z0-9\-\_]+$', value) is None:
78 raise formencode.Invalid(_('Username may only contain '
78 raise formencode.Invalid(_('Username may only contain '
79 'alphanumeric characters '
79 'alphanumeric characters underscores '
80 'or dashes and cannot begin with a dash'),
80 'or dashes and must begin with '
81 'alphanumeric character'),
81 value, state)
82 value, state)
82
83
83
84
84
85
85 return _ValidUsername
86 return _ValidUsername
86
87
87 class ValidPassword(formencode.validators.FancyValidator):
88 class ValidPassword(formencode.validators.FancyValidator):
88
89
89 def to_python(self, value, state):
90 def to_python(self, value, state):
90
91
91 if value:
92 if value:
92
93
93 if value.get('password'):
94 if value.get('password'):
94 try:
95 try:
95 value['password'] = get_crypt_password(value['password'])
96 value['password'] = get_crypt_password(value['password'])
96 except UnicodeEncodeError:
97 except UnicodeEncodeError:
97 e_dict = {'password':_('Invalid characters in password')}
98 e_dict = {'password':_('Invalid characters in password')}
98 raise formencode.Invalid('', value, state, error_dict=e_dict)
99 raise formencode.Invalid('', value, state, error_dict=e_dict)
99
100
100 if value.get('password_confirmation'):
101 if value.get('password_confirmation'):
101 try:
102 try:
102 value['password_confirmation'] = \
103 value['password_confirmation'] = \
103 get_crypt_password(value['password_confirmation'])
104 get_crypt_password(value['password_confirmation'])
104 except UnicodeEncodeError:
105 except UnicodeEncodeError:
105 e_dict = {'password_confirmation':_('Invalid characters in password')}
106 e_dict = {'password_confirmation':_('Invalid characters in password')}
106 raise formencode.Invalid('', value, state, error_dict=e_dict)
107 raise formencode.Invalid('', value, state, error_dict=e_dict)
107
108
108 if value.get('new_password'):
109 if value.get('new_password'):
109 try:
110 try:
110 value['new_password'] = \
111 value['new_password'] = \
111 get_crypt_password(value['new_password'])
112 get_crypt_password(value['new_password'])
112 except UnicodeEncodeError:
113 except UnicodeEncodeError:
113 e_dict = {'new_password':_('Invalid characters in password')}
114 e_dict = {'new_password':_('Invalid characters in password')}
114 raise formencode.Invalid('', value, state, error_dict=e_dict)
115 raise formencode.Invalid('', value, state, error_dict=e_dict)
115
116
116 return value
117 return value
117
118
118 class ValidPasswordsMatch(formencode.validators.FancyValidator):
119 class ValidPasswordsMatch(formencode.validators.FancyValidator):
119
120
120 def validate_python(self, value, state):
121 def validate_python(self, value, state):
121
122
122 if value['password'] != value['password_confirmation']:
123 if value['password'] != value['password_confirmation']:
123 e_dict = {'password_confirmation':
124 e_dict = {'password_confirmation':
124 _('Password do not match')}
125 _('Password do not match')}
125 raise formencode.Invalid('', value, state, error_dict=e_dict)
126 raise formencode.Invalid('', value, state, error_dict=e_dict)
126
127
127 class ValidAuth(formencode.validators.FancyValidator):
128 class ValidAuth(formencode.validators.FancyValidator):
128 messages = {
129 messages = {
129 'invalid_password':_('invalid password'),
130 'invalid_password':_('invalid password'),
130 'invalid_login':_('invalid user name'),
131 'invalid_login':_('invalid user name'),
131 'disabled_account':_('Your account is disabled')
132 'disabled_account':_('Your account is disabled')
132
133
133 }
134 }
134 #error mapping
135 #error mapping
135 e_dict = {'username':messages['invalid_login'],
136 e_dict = {'username':messages['invalid_login'],
136 'password':messages['invalid_password']}
137 'password':messages['invalid_password']}
137 e_dict_disable = {'username':messages['disabled_account']}
138 e_dict_disable = {'username':messages['disabled_account']}
138
139
139 def validate_python(self, value, state):
140 def validate_python(self, value, state):
140 password = value['password']
141 password = value['password']
141 username = value['username']
142 username = value['username']
142 user = UserModel().get_by_username(username)
143 user = UserModel().get_by_username(username)
143
144
144 if authfunc(None, username, password):
145 if authfunc(None, username, password):
145 return value
146 return value
146 else:
147 else:
147 if user and user.active is False:
148 if user and user.active is False:
148 log.warning('user %s is disabled', username)
149 log.warning('user %s is disabled', username)
149 raise formencode.Invalid(self.message('disabled_account',
150 raise formencode.Invalid(self.message('disabled_account',
150 state=State_obj),
151 state=State_obj),
151 value, state,
152 value, state,
152 error_dict=self.e_dict_disable)
153 error_dict=self.e_dict_disable)
153 else:
154 else:
154 log.warning('user %s not authenticated', username)
155 log.warning('user %s not authenticated', username)
155 raise formencode.Invalid(self.message('invalid_password',
156 raise formencode.Invalid(self.message('invalid_password',
156 state=State_obj), value, state,
157 state=State_obj), value, state,
157 error_dict=self.e_dict)
158 error_dict=self.e_dict)
158
159
159 class ValidRepoUser(formencode.validators.FancyValidator):
160 class ValidRepoUser(formencode.validators.FancyValidator):
160
161
161 def to_python(self, value, state):
162 def to_python(self, value, state):
162 sa = meta.Session()
163 sa = meta.Session()
163 try:
164 try:
164 self.user_db = sa.query(User)\
165 self.user_db = sa.query(User)\
165 .filter(User.active == True)\
166 .filter(User.active == True)\
166 .filter(User.username == value).one()
167 .filter(User.username == value).one()
167 except Exception:
168 except Exception:
168 raise formencode.Invalid(_('This username is not valid'),
169 raise formencode.Invalid(_('This username is not valid'),
169 value, state)
170 value, state)
170 finally:
171 finally:
171 meta.Session.remove()
172 meta.Session.remove()
172
173
173 return self.user_db.user_id
174 return self.user_db.user_id
174
175
175 def ValidRepoName(edit, old_data):
176 def ValidRepoName(edit, old_data):
176 class _ValidRepoName(formencode.validators.FancyValidator):
177 class _ValidRepoName(formencode.validators.FancyValidator):
177
178
178 def to_python(self, value, state):
179 def to_python(self, value, state):
179 slug = h.repo_name_slug(value)
180 slug = h.repo_name_slug(value)
180 if slug in ['_admin']:
181 if slug in ['_admin']:
181 raise formencode.Invalid(_('This repository name is disallowed'),
182 raise formencode.Invalid(_('This repository name is disallowed'),
182 value, state)
183 value, state)
183 if old_data.get('repo_name') != value or not edit:
184 if old_data.get('repo_name') != value or not edit:
184 if RepoModel().get_by_repo_name(slug, cache=False):
185 if RepoModel().get_by_repo_name(slug, cache=False):
185 raise formencode.Invalid(_('This repository already exists') ,
186 raise formencode.Invalid(_('This repository already exists') ,
186 value, state)
187 value, state)
187 return slug
188 return slug
188
189
189
190
190 return _ValidRepoName
191 return _ValidRepoName
191
192
192 def ValidForkType(old_data):
193 def ValidForkType(old_data):
193 class _ValidForkType(formencode.validators.FancyValidator):
194 class _ValidForkType(formencode.validators.FancyValidator):
194
195
195 def to_python(self, value, state):
196 def to_python(self, value, state):
196 if old_data['repo_type'] != value:
197 if old_data['repo_type'] != value:
197 raise formencode.Invalid(_('Fork have to be the same type as original'),
198 raise formencode.Invalid(_('Fork have to be the same type as original'),
198 value, state)
199 value, state)
199 return value
200 return value
200 return _ValidForkType
201 return _ValidForkType
201
202
202 class ValidPerms(formencode.validators.FancyValidator):
203 class ValidPerms(formencode.validators.FancyValidator):
203 messages = {'perm_new_user_name':_('This username is not valid')}
204 messages = {'perm_new_user_name':_('This username is not valid')}
204
205
205 def to_python(self, value, state):
206 def to_python(self, value, state):
206 perms_update = []
207 perms_update = []
207 perms_new = []
208 perms_new = []
208 #build a list of permission to update and new permission to create
209 #build a list of permission to update and new permission to create
209 for k, v in value.items():
210 for k, v in value.items():
210 if k.startswith('perm_'):
211 if k.startswith('perm_'):
211 if k.startswith('perm_new_user'):
212 if k.startswith('perm_new_user'):
212 new_perm = value.get('perm_new_user', False)
213 new_perm = value.get('perm_new_user', False)
213 new_user = value.get('perm_new_user_name', False)
214 new_user = value.get('perm_new_user_name', False)
214 if new_user and new_perm:
215 if new_user and new_perm:
215 if (new_user, new_perm) not in perms_new:
216 if (new_user, new_perm) not in perms_new:
216 perms_new.append((new_user, new_perm))
217 perms_new.append((new_user, new_perm))
217 else:
218 else:
218 usr = k[5:]
219 usr = k[5:]
219 if usr == 'default':
220 if usr == 'default':
220 if value['private']:
221 if value['private']:
221 #set none for default when updating to private repo
222 #set none for default when updating to private repo
222 v = 'repository.none'
223 v = 'repository.none'
223 perms_update.append((usr, v))
224 perms_update.append((usr, v))
224 value['perms_updates'] = perms_update
225 value['perms_updates'] = perms_update
225 value['perms_new'] = perms_new
226 value['perms_new'] = perms_new
226 sa = meta.Session
227 sa = meta.Session
227 for k, v in perms_new:
228 for k, v in perms_new:
228 try:
229 try:
229 self.user_db = sa.query(User)\
230 self.user_db = sa.query(User)\
230 .filter(User.active == True)\
231 .filter(User.active == True)\
231 .filter(User.username == k).one()
232 .filter(User.username == k).one()
232 except Exception:
233 except Exception:
233 msg = self.message('perm_new_user_name',
234 msg = self.message('perm_new_user_name',
234 state=State_obj)
235 state=State_obj)
235 raise formencode.Invalid(msg, value, state,
236 raise formencode.Invalid(msg, value, state,
236 error_dict={'perm_new_user_name':msg})
237 error_dict={'perm_new_user_name':msg})
237 return value
238 return value
238
239
239 class ValidSettings(formencode.validators.FancyValidator):
240 class ValidSettings(formencode.validators.FancyValidator):
240
241
241 def to_python(self, value, state):
242 def to_python(self, value, state):
242 #settings form can't edit user
243 #settings form can't edit user
243 if value.has_key('user'):
244 if value.has_key('user'):
244 del['value']['user']
245 del['value']['user']
245
246
246 return value
247 return value
247
248
248 class ValidPath(formencode.validators.FancyValidator):
249 class ValidPath(formencode.validators.FancyValidator):
249 def to_python(self, value, state):
250 def to_python(self, value, state):
250
251
251 if not os.path.isdir(value):
252 if not os.path.isdir(value):
252 msg = _('This is not a valid path')
253 msg = _('This is not a valid path')
253 raise formencode.Invalid(msg, value, state,
254 raise formencode.Invalid(msg, value, state,
254 error_dict={'paths_root_path':msg})
255 error_dict={'paths_root_path':msg})
255 return value
256 return value
256
257
257 def UniqSystemEmail(old_data):
258 def UniqSystemEmail(old_data):
258 class _UniqSystemEmail(formencode.validators.FancyValidator):
259 class _UniqSystemEmail(formencode.validators.FancyValidator):
259 def to_python(self, value, state):
260 def to_python(self, value, state):
260 value = value.lower()
261 value = value.lower()
261 #TODO:write test for MixedCase scenarios
262 if old_data.get('email') != value:
262 if old_data.get('email') != value:
263 sa = meta.Session()
263 sa = meta.Session()
264 try:
264 try:
265 user = sa.query(User).filter(User.email == value).scalar()
265 user = sa.query(User).filter(User.email == value).scalar()
266 if user:
266 if user:
267 raise formencode.Invalid(_("That e-mail address is already taken") ,
267 raise formencode.Invalid(_("That e-mail address is already taken") ,
268 value, state)
268 value, state)
269 finally:
269 finally:
270 meta.Session.remove()
270 meta.Session.remove()
271
271
272 return value
272 return value
273
273
274 return _UniqSystemEmail
274 return _UniqSystemEmail
275
275
276 class ValidSystemEmail(formencode.validators.FancyValidator):
276 class ValidSystemEmail(formencode.validators.FancyValidator):
277 def to_python(self, value, state):
277 def to_python(self, value, state):
278 value = value.lower()
278 value = value.lower()
279 sa = meta.Session
279 sa = meta.Session
280 try:
280 try:
281 user = sa.query(User).filter(User.email == value).scalar()
281 user = sa.query(User).filter(User.email == value).scalar()
282 if user is None:
282 if user is None:
283 raise formencode.Invalid(_("That e-mail address doesn't exist.") ,
283 raise formencode.Invalid(_("That e-mail address doesn't exist.") ,
284 value, state)
284 value, state)
285 finally:
285 finally:
286 meta.Session.remove()
286 meta.Session.remove()
287
287
288 return value
288 return value
289
289
290 class LdapLibValidator(formencode.validators.FancyValidator):
290 class LdapLibValidator(formencode.validators.FancyValidator):
291
291
292 def to_python(self, value, state):
292 def to_python(self, value, state):
293
293
294 try:
294 try:
295 import ldap
295 import ldap
296 except ImportError:
296 except ImportError:
297 raise LdapImportError
297 raise LdapImportError
298 return value
298 return value
299
299
300 #===============================================================================
300 #===============================================================================
301 # FORMS
301 # FORMS
302 #===============================================================================
302 #===============================================================================
303 class LoginForm(formencode.Schema):
303 class LoginForm(formencode.Schema):
304 allow_extra_fields = True
304 allow_extra_fields = True
305 filter_extra_fields = True
305 filter_extra_fields = True
306 username = UnicodeString(
306 username = UnicodeString(
307 strip=True,
307 strip=True,
308 min=1,
308 min=1,
309 not_empty=True,
309 not_empty=True,
310 messages={
310 messages={
311 'empty':_('Please enter a login'),
311 'empty':_('Please enter a login'),
312 'tooShort':_('Enter a value %(min)i characters long or more')}
312 'tooShort':_('Enter a value %(min)i characters long or more')}
313 )
313 )
314
314
315 password = UnicodeString(
315 password = UnicodeString(
316 strip=True,
316 strip=True,
317 min=6,
317 min=6,
318 not_empty=True,
318 not_empty=True,
319 messages={
319 messages={
320 'empty':_('Please enter a password'),
320 'empty':_('Please enter a password'),
321 'tooShort':_('Enter %(min)i characters or more')}
321 'tooShort':_('Enter %(min)i characters or more')}
322 )
322 )
323
323
324
324
325 #chained validators have access to all data
325 #chained validators have access to all data
326 chained_validators = [ValidAuth]
326 chained_validators = [ValidAuth]
327
327
328 def UserForm(edit=False, old_data={}):
328 def UserForm(edit=False, old_data={}):
329 class _UserForm(formencode.Schema):
329 class _UserForm(formencode.Schema):
330 allow_extra_fields = True
330 allow_extra_fields = True
331 filter_extra_fields = True
331 filter_extra_fields = True
332 username = All(UnicodeString(strip=True, min=1, not_empty=True),
332 username = All(UnicodeString(strip=True, min=1, not_empty=True),
333 ValidUsername(edit, old_data))
333 ValidUsername(edit, old_data))
334 if edit:
334 if edit:
335 new_password = All(UnicodeString(strip=True, min=6, not_empty=False))
335 new_password = All(UnicodeString(strip=True, min=6, not_empty=False))
336 admin = StringBoolean(if_missing=False)
336 admin = StringBoolean(if_missing=False)
337 else:
337 else:
338 password = All(UnicodeString(strip=True, min=6, not_empty=True))
338 password = All(UnicodeString(strip=True, min=6, not_empty=True))
339 active = StringBoolean(if_missing=False)
339 active = StringBoolean(if_missing=False)
340 name = UnicodeString(strip=True, min=1, not_empty=True)
340 name = UnicodeString(strip=True, min=1, not_empty=True)
341 lastname = UnicodeString(strip=True, min=1, not_empty=True)
341 lastname = UnicodeString(strip=True, min=1, not_empty=True)
342 email = All(Email(not_empty=True), UniqSystemEmail(old_data))
342 email = All(Email(not_empty=True), UniqSystemEmail(old_data))
343
343
344 chained_validators = [ValidPassword]
344 chained_validators = [ValidPassword]
345
345
346 return _UserForm
346 return _UserForm
347
347
348 def RegisterForm(edit=False, old_data={}):
348 def RegisterForm(edit=False, old_data={}):
349 class _RegisterForm(formencode.Schema):
349 class _RegisterForm(formencode.Schema):
350 allow_extra_fields = True
350 allow_extra_fields = True
351 filter_extra_fields = True
351 filter_extra_fields = True
352 username = All(ValidUsername(edit, old_data),
352 username = All(ValidUsername(edit, old_data),
353 UnicodeString(strip=True, min=1, not_empty=True))
353 UnicodeString(strip=True, min=1, not_empty=True))
354 password = All(UnicodeString(strip=True, min=6, not_empty=True))
354 password = All(UnicodeString(strip=True, min=6, not_empty=True))
355 password_confirmation = All(UnicodeString(strip=True, min=6, not_empty=True))
355 password_confirmation = All(UnicodeString(strip=True, min=6, not_empty=True))
356 active = StringBoolean(if_missing=False)
356 active = StringBoolean(if_missing=False)
357 name = UnicodeString(strip=True, min=1, not_empty=True)
357 name = UnicodeString(strip=True, min=1, not_empty=True)
358 lastname = UnicodeString(strip=True, min=1, not_empty=True)
358 lastname = UnicodeString(strip=True, min=1, not_empty=True)
359 email = All(Email(not_empty=True), UniqSystemEmail(old_data))
359 email = All(Email(not_empty=True), UniqSystemEmail(old_data))
360
360
361 chained_validators = [ValidPasswordsMatch, ValidPassword]
361 chained_validators = [ValidPasswordsMatch, ValidPassword]
362
362
363 return _RegisterForm
363 return _RegisterForm
364
364
365 def PasswordResetForm():
365 def PasswordResetForm():
366 class _PasswordResetForm(formencode.Schema):
366 class _PasswordResetForm(formencode.Schema):
367 allow_extra_fields = True
367 allow_extra_fields = True
368 filter_extra_fields = True
368 filter_extra_fields = True
369 email = All(ValidSystemEmail(), Email(not_empty=True))
369 email = All(ValidSystemEmail(), Email(not_empty=True))
370 return _PasswordResetForm
370 return _PasswordResetForm
371
371
372 def RepoForm(edit=False, old_data={}, supported_backends=BACKENDS.keys()):
372 def RepoForm(edit=False, old_data={}, supported_backends=BACKENDS.keys()):
373 class _RepoForm(formencode.Schema):
373 class _RepoForm(formencode.Schema):
374 allow_extra_fields = True
374 allow_extra_fields = True
375 filter_extra_fields = False
375 filter_extra_fields = False
376 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True),
376 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True),
377 ValidRepoName(edit, old_data))
377 ValidRepoName(edit, old_data))
378 description = UnicodeString(strip=True, min=1, not_empty=True)
378 description = UnicodeString(strip=True, min=1, not_empty=True)
379 private = StringBoolean(if_missing=False)
379 private = StringBoolean(if_missing=False)
380 repo_type = OneOf(supported_backends)
380 repo_type = OneOf(supported_backends)
381 if edit:
381 if edit:
382 user = All(Int(not_empty=True), ValidRepoUser)
382 user = All(Int(not_empty=True), ValidRepoUser)
383
383
384 chained_validators = [ValidPerms]
384 chained_validators = [ValidPerms]
385 return _RepoForm
385 return _RepoForm
386
386
387 def RepoForkForm(edit=False, old_data={}, supported_backends=BACKENDS.keys()):
387 def RepoForkForm(edit=False, old_data={}, supported_backends=BACKENDS.keys()):
388 class _RepoForkForm(formencode.Schema):
388 class _RepoForkForm(formencode.Schema):
389 allow_extra_fields = True
389 allow_extra_fields = True
390 filter_extra_fields = False
390 filter_extra_fields = False
391 fork_name = All(UnicodeString(strip=True, min=1, not_empty=True),
391 fork_name = All(UnicodeString(strip=True, min=1, not_empty=True),
392 ValidRepoName(edit, old_data))
392 ValidRepoName(edit, old_data))
393 description = UnicodeString(strip=True, min=1, not_empty=True)
393 description = UnicodeString(strip=True, min=1, not_empty=True)
394 private = StringBoolean(if_missing=False)
394 private = StringBoolean(if_missing=False)
395 repo_type = All(ValidForkType(old_data), OneOf(supported_backends))
395 repo_type = All(ValidForkType(old_data), OneOf(supported_backends))
396 return _RepoForkForm
396 return _RepoForkForm
397
397
398 def RepoSettingsForm(edit=False, old_data={}):
398 def RepoSettingsForm(edit=False, old_data={}):
399 class _RepoForm(formencode.Schema):
399 class _RepoForm(formencode.Schema):
400 allow_extra_fields = True
400 allow_extra_fields = True
401 filter_extra_fields = False
401 filter_extra_fields = False
402 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True),
402 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True),
403 ValidRepoName(edit, old_data))
403 ValidRepoName(edit, old_data))
404 description = UnicodeString(strip=True, min=1, not_empty=True)
404 description = UnicodeString(strip=True, min=1, not_empty=True)
405 private = StringBoolean(if_missing=False)
405 private = StringBoolean(if_missing=False)
406
406
407 chained_validators = [ValidPerms, ValidSettings]
407 chained_validators = [ValidPerms, ValidSettings]
408 return _RepoForm
408 return _RepoForm
409
409
410
410
411 def ApplicationSettingsForm():
411 def ApplicationSettingsForm():
412 class _ApplicationSettingsForm(formencode.Schema):
412 class _ApplicationSettingsForm(formencode.Schema):
413 allow_extra_fields = True
413 allow_extra_fields = True
414 filter_extra_fields = False
414 filter_extra_fields = False
415 rhodecode_title = UnicodeString(strip=True, min=1, not_empty=True)
415 rhodecode_title = UnicodeString(strip=True, min=1, not_empty=True)
416 rhodecode_realm = UnicodeString(strip=True, min=1, not_empty=True)
416 rhodecode_realm = UnicodeString(strip=True, min=1, not_empty=True)
417
417
418 return _ApplicationSettingsForm
418 return _ApplicationSettingsForm
419
419
420 def ApplicationUiSettingsForm():
420 def ApplicationUiSettingsForm():
421 class _ApplicationUiSettingsForm(formencode.Schema):
421 class _ApplicationUiSettingsForm(formencode.Schema):
422 allow_extra_fields = True
422 allow_extra_fields = True
423 filter_extra_fields = False
423 filter_extra_fields = False
424 web_push_ssl = OneOf(['true', 'false'], if_missing='false')
424 web_push_ssl = OneOf(['true', 'false'], if_missing='false')
425 paths_root_path = All(ValidPath(), UnicodeString(strip=True, min=1, not_empty=True))
425 paths_root_path = All(ValidPath(), UnicodeString(strip=True, min=1, not_empty=True))
426 hooks_changegroup_update = OneOf(['True', 'False'], if_missing=False)
426 hooks_changegroup_update = OneOf(['True', 'False'], if_missing=False)
427 hooks_changegroup_repo_size = OneOf(['True', 'False'], if_missing=False)
427 hooks_changegroup_repo_size = OneOf(['True', 'False'], if_missing=False)
428 hooks_pretxnchangegroup_push_logger = OneOf(['True', 'False'], if_missing=False)
428 hooks_pretxnchangegroup_push_logger = OneOf(['True', 'False'], if_missing=False)
429 hooks_preoutgoing_pull_logger = OneOf(['True', 'False'], if_missing=False)
429 hooks_preoutgoing_pull_logger = OneOf(['True', 'False'], if_missing=False)
430
430
431 return _ApplicationUiSettingsForm
431 return _ApplicationUiSettingsForm
432
432
433 def DefaultPermissionsForm(perms_choices, register_choices, create_choices):
433 def DefaultPermissionsForm(perms_choices, register_choices, create_choices):
434 class _DefaultPermissionsForm(formencode.Schema):
434 class _DefaultPermissionsForm(formencode.Schema):
435 allow_extra_fields = True
435 allow_extra_fields = True
436 filter_extra_fields = True
436 filter_extra_fields = True
437 overwrite_default = StringBoolean(if_missing=False)
437 overwrite_default = StringBoolean(if_missing=False)
438 anonymous = OneOf(['True', 'False'], if_missing=False)
438 anonymous = OneOf(['True', 'False'], if_missing=False)
439 default_perm = OneOf(perms_choices)
439 default_perm = OneOf(perms_choices)
440 default_register = OneOf(register_choices)
440 default_register = OneOf(register_choices)
441 default_create = OneOf(create_choices)
441 default_create = OneOf(create_choices)
442
442
443 return _DefaultPermissionsForm
443 return _DefaultPermissionsForm
444
444
445
445
446 def LdapSettingsForm():
446 def LdapSettingsForm():
447 class _LdapSettingsForm(formencode.Schema):
447 class _LdapSettingsForm(formencode.Schema):
448 allow_extra_fields = True
448 allow_extra_fields = True
449 filter_extra_fields = True
449 filter_extra_fields = True
450 pre_validators = [LdapLibValidator]
450 pre_validators = [LdapLibValidator]
451 ldap_active = StringBoolean(if_missing=False)
451 ldap_active = StringBoolean(if_missing=False)
452 ldap_host = UnicodeString(strip=True,)
452 ldap_host = UnicodeString(strip=True,)
453 ldap_port = Number(strip=True,)
453 ldap_port = Number(strip=True,)
454 ldap_ldaps = StringBoolean(if_missing=False)
454 ldap_ldaps = StringBoolean(if_missing=False)
455 ldap_dn_user = UnicodeString(strip=True,)
455 ldap_dn_user = UnicodeString(strip=True,)
456 ldap_dn_pass = UnicodeString(strip=True,)
456 ldap_dn_pass = UnicodeString(strip=True,)
457 ldap_base_dn = UnicodeString(strip=True,)
457 ldap_base_dn = UnicodeString(strip=True,)
458
458
459 return _LdapSettingsForm
459 return _LdapSettingsForm
@@ -1,178 +1,230 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 from rhodecode.tests import *
2 from rhodecode.tests import *
3 from rhodecode.model.db import User
3 from rhodecode.model.db import User
4 from rhodecode.lib.auth import check_password
4 from rhodecode.lib.auth import check_password
5
5
6
6
7 class TestLoginController(TestController):
7 class TestLoginController(TestController):
8
8
9 def test_index(self):
9 def test_index(self):
10 response = self.app.get(url(controller='login', action='index'))
10 response = self.app.get(url(controller='login', action='index'))
11 assert response.status == '200 OK', 'Wrong response from login page got %s' % response.status
11 assert response.status == '200 OK', 'Wrong response from login page got %s' % response.status
12 # Test response...
12 # Test response...
13
13
14 def test_login_admin_ok(self):
14 def test_login_admin_ok(self):
15 response = self.app.post(url(controller='login', action='index'),
15 response = self.app.post(url(controller='login', action='index'),
16 {'username':'test_admin',
16 {'username':'test_admin',
17 'password':'test12'})
17 'password':'test12'})
18 assert response.status == '302 Found', 'Wrong response code from login got %s' % response.status
18 assert response.status == '302 Found', 'Wrong response code from login got %s' % response.status
19 assert response.session['rhodecode_user'].username == 'test_admin', 'wrong logged in user'
19 assert response.session['rhodecode_user'].username == 'test_admin', 'wrong logged in user'
20 response = response.follow()
20 response = response.follow()
21 assert '%s repository' % HG_REPO in response.body
21 assert '%s repository' % HG_REPO in response.body
22
22
23 def test_login_regular_ok(self):
23 def test_login_regular_ok(self):
24 response = self.app.post(url(controller='login', action='index'),
24 response = self.app.post(url(controller='login', action='index'),
25 {'username':'test_regular',
25 {'username':'test_regular',
26 'password':'test12'})
26 'password':'test12'})
27 print response
27 print response
28 assert response.status == '302 Found', 'Wrong response code from login got %s' % response.status
28 assert response.status == '302 Found', 'Wrong response code from login got %s' % response.status
29 assert response.session['rhodecode_user'].username == 'test_regular', 'wrong logged in user'
29 assert response.session['rhodecode_user'].username == 'test_regular', 'wrong logged in user'
30 response = response.follow()
30 response = response.follow()
31 assert '%s repository' % HG_REPO in response.body
31 assert '%s repository' % HG_REPO in response.body
32 assert '<a title="Admin" href="/_admin">' not in response.body
32 assert '<a title="Admin" href="/_admin">' not in response.body
33
33
34 def test_login_ok_came_from(self):
34 def test_login_ok_came_from(self):
35 test_came_from = '/_admin/users'
35 test_came_from = '/_admin/users'
36 response = self.app.post(url(controller='login', action='index', came_from=test_came_from),
36 response = self.app.post(url(controller='login', action='index', came_from=test_came_from),
37 {'username':'test_admin',
37 {'username':'test_admin',
38 'password':'test12'})
38 'password':'test12'})
39 assert response.status == '302 Found', 'Wrong response code from came from redirection'
39 assert response.status == '302 Found', 'Wrong response code from came from redirection'
40 response = response.follow()
40 response = response.follow()
41
41
42 assert response.status == '200 OK', 'Wrong response from login page got %s' % response.status
42 assert response.status == '200 OK', 'Wrong response from login page got %s' % response.status
43 assert 'Users administration' in response.body, 'No proper title in response'
43 assert 'Users administration' in response.body, 'No proper title in response'
44
44
45
45
46 def test_login_short_password(self):
46 def test_login_short_password(self):
47 response = self.app.post(url(controller='login', action='index'),
47 response = self.app.post(url(controller='login', action='index'),
48 {'username':'error',
48 {'username':'error',
49 'password':'test'})
49 'password':'test'})
50 assert response.status == '200 OK', 'Wrong response from login page'
50 assert response.status == '200 OK', 'Wrong response from login page'
51 print response.body
51 print response.body
52 assert 'Enter 6 characters or more' in response.body, 'No error password message in response'
52 assert 'Enter 6 characters or more' in response.body, 'No error password message in response'
53
53
54 def test_login_wrong_username_password(self):
54 def test_login_wrong_username_password(self):
55 response = self.app.post(url(controller='login', action='index'),
55 response = self.app.post(url(controller='login', action='index'),
56 {'username':'error',
56 {'username':'error',
57 'password':'test12'})
57 'password':'test12'})
58 assert response.status == '200 OK', 'Wrong response from login page'
58 assert response.status == '200 OK', 'Wrong response from login page'
59
59
60 assert 'invalid user name' in response.body, 'No error username message in response'
60 assert 'invalid user name' in response.body, 'No error username message in response'
61 assert 'invalid password' in response.body, 'No error password message in response'
61 assert 'invalid password' in response.body, 'No error password message in response'
62
62
63 #==========================================================================
63 #==========================================================================
64 # REGISTRATIONS
64 # REGISTRATIONS
65 #==========================================================================
65 #==========================================================================
66 def test_register(self):
66 def test_register(self):
67 response = self.app.get(url(controller='login', action='register'))
67 response = self.app.get(url(controller='login', action='register'))
68 assert 'Sign Up to RhodeCode' in response.body, 'wrong page for user registration'
68 assert 'Sign Up to RhodeCode' in response.body, 'wrong page for user registration'
69
69
70 def test_register_err_same_username(self):
70 def test_register_err_same_username(self):
71 response = self.app.post(url(controller='login', action='register'),
71 response = self.app.post(url(controller='login', action='register'),
72 {'username':'test_admin',
72 {'username':'test_admin',
73 'password':'test12',
73 'password':'test12',
74 'password_confirmation':'test12',
74 'password_confirmation':'test12',
75 'email':'goodmail@domain.com',
75 'email':'goodmail@domain.com',
76 'name':'test',
76 'name':'test',
77 'lastname':'test'})
77 'lastname':'test'})
78
78
79 assert response.status == '200 OK', 'Wrong response from register page got %s' % response.status
79 assert response.status == '200 OK', 'Wrong response from register page got %s' % response.status
80 assert 'This username already exists' in response.body
80 assert 'This username already exists' in response.body
81
81
82 def test_register_err_same_email(self):
83 response = self.app.post(url(controller='login', action='register'),
84 {'username':'test_admin_0',
85 'password':'test12',
86 'password_confirmation':'test12',
87 'email':'test_admin@mail.com',
88 'name':'test',
89 'lastname':'test'})
90
91 assert response.status == '200 OK', 'Wrong response from register page got %s' % response.status
92 assert 'That e-mail address is already taken' in response.body
93
94 def test_register_err_same_email_case_sensitive(self):
95 response = self.app.post(url(controller='login', action='register'),
96 {'username':'test_admin_1',
97 'password':'test12',
98 'password_confirmation':'test12',
99 'email':'TesT_Admin@mail.COM',
100 'name':'test',
101 'lastname':'test'})
102 assert response.status == '200 OK', 'Wrong response from register page got %s' % response.status
103 assert 'That e-mail address is already taken' in response.body
104
82 def test_register_err_wrong_data(self):
105 def test_register_err_wrong_data(self):
83 response = self.app.post(url(controller='login', action='register'),
106 response = self.app.post(url(controller='login', action='register'),
84 {'username':'xs',
107 {'username':'xs',
85 'password':'test',
108 'password':'test',
86 'password_confirmation':'test',
109 'password_confirmation':'test',
87 'email':'goodmailm',
110 'email':'goodmailm',
88 'name':'test',
111 'name':'test',
89 'lastname':'test'})
112 'lastname':'test'})
90 assert response.status == '200 OK', 'Wrong response from register page got %s' % response.status
113 assert response.status == '200 OK', 'Wrong response from register page got %s' % response.status
91 assert 'An email address must contain a single @' in response.body
114 assert 'An email address must contain a single @' in response.body
92 assert 'Enter a value 6 characters long or more' in response.body
115 assert 'Enter a value 6 characters long or more' in response.body
93
116
94
117
118 def test_register_err_username(self):
119 response = self.app.post(url(controller='login', action='register'),
120 {'username':'error user',
121 'password':'test12',
122 'password_confirmation':'test12',
123 'email':'goodmailm',
124 'name':'test',
125 'lastname':'test'})
126
127 print response.body
128 assert response.status == '200 OK', 'Wrong response from register page got %s' % response.status
129 assert 'An email address must contain a single @' in response.body
130 assert 'Username may only contain alphanumeric characters underscores or dashes and must begin with alphanumeric character' in response.body
131
132 def test_register_err_case_sensitive(self):
133 response = self.app.post(url(controller='login', action='register'),
134 {'username':'Test_Admin',
135 'password':'test12',
136 'password_confirmation':'test12',
137 'email':'goodmailm',
138 'name':'test',
139 'lastname':'test'})
140
141 assert response.status == '200 OK', 'Wrong response from register page got %s' % response.status
142 assert 'An email address must contain a single @' in response.body
143 assert 'This username already exists' in response.body
144
145
146
95 def test_register_special_chars(self):
147 def test_register_special_chars(self):
96 response = self.app.post(url(controller='login', action='register'),
148 response = self.app.post(url(controller='login', action='register'),
97 {'username':'xxxaxn',
149 {'username':'xxxaxn',
98 'password':'Δ…Δ‡ΕΊΕΌΔ…Ε›Ε›Ε›Ε›',
150 'password':'Δ…Δ‡ΕΊΕΌΔ…Ε›Ε›Ε›Ε›',
99 'password_confirmation':'Δ…Δ‡ΕΊΕΌΔ…Ε›Ε›Ε›Ε›',
151 'password_confirmation':'Δ…Δ‡ΕΊΕΌΔ…Ε›Ε›Ε›Ε›',
100 'email':'goodmailm@test.plx',
152 'email':'goodmailm@test.plx',
101 'name':'test',
153 'name':'test',
102 'lastname':'test'})
154 'lastname':'test'})
103
155
104 print response.body
156 print response.body
105 assert response.status == '200 OK', 'Wrong response from register page got %s' % response.status
157 assert response.status == '200 OK', 'Wrong response from register page got %s' % response.status
106 assert 'Invalid characters in password' in response.body
158 assert 'Invalid characters in password' in response.body
107
159
108
160
109 def test_register_password_mismatch(self):
161 def test_register_password_mismatch(self):
110 response = self.app.post(url(controller='login', action='register'),
162 response = self.app.post(url(controller='login', action='register'),
111 {'username':'xs',
163 {'username':'xs',
112 'password':'123qwe',
164 'password':'123qwe',
113 'password_confirmation':'qwe123',
165 'password_confirmation':'qwe123',
114 'email':'goodmailm@test.plxa',
166 'email':'goodmailm@test.plxa',
115 'name':'test',
167 'name':'test',
116 'lastname':'test'})
168 'lastname':'test'})
117
169
118 assert response.status == '200 OK', 'Wrong response from register page got %s' % response.status
170 assert response.status == '200 OK', 'Wrong response from register page got %s' % response.status
119 print response.body
171 print response.body
120 assert 'Password do not match' in response.body
172 assert 'Password do not match' in response.body
121
173
122 def test_register_ok(self):
174 def test_register_ok(self):
123 username = 'test_regular4'
175 username = 'test_regular4'
124 password = 'qweqwe'
176 password = 'qweqwe'
125 email = 'marcin@test.com'
177 email = 'marcin@test.com'
126 name = 'testname'
178 name = 'testname'
127 lastname = 'testlastname'
179 lastname = 'testlastname'
128
180
129 response = self.app.post(url(controller='login', action='register'),
181 response = self.app.post(url(controller='login', action='register'),
130 {'username':username,
182 {'username':username,
131 'password':password,
183 'password':password,
132 'password_confirmation':password,
184 'password_confirmation':password,
133 'email':email,
185 'email':email,
134 'name':name,
186 'name':name,
135 'lastname':lastname})
187 'lastname':lastname})
136 assert response.status == '302 Found', 'Wrong response from register page got %s' % response.status
188 assert response.status == '302 Found', 'Wrong response from register page got %s' % response.status
137 assert 'You have successfully registered into rhodecode' in response.session['flash'][0], 'No flash message about user registration'
189 assert 'You have successfully registered into rhodecode' in response.session['flash'][0], 'No flash message about user registration'
138
190
139 ret = self.sa.query(User).filter(User.username == 'test_regular4').one()
191 ret = self.sa.query(User).filter(User.username == 'test_regular4').one()
140 assert ret.username == username , 'field mismatch %s %s' % (ret.username, username)
192 assert ret.username == username , 'field mismatch %s %s' % (ret.username, username)
141 assert check_password(password, ret.password) == True , 'password mismatch'
193 assert check_password(password, ret.password) == True , 'password mismatch'
142 assert ret.email == email , 'field mismatch %s %s' % (ret.email, email)
194 assert ret.email == email , 'field mismatch %s %s' % (ret.email, email)
143 assert ret.name == name , 'field mismatch %s %s' % (ret.name, name)
195 assert ret.name == name , 'field mismatch %s %s' % (ret.name, name)
144 assert ret.lastname == lastname , 'field mismatch %s %s' % (ret.lastname, lastname)
196 assert ret.lastname == lastname , 'field mismatch %s %s' % (ret.lastname, lastname)
145
197
146
198
147 def test_forgot_password_wrong_mail(self):
199 def test_forgot_password_wrong_mail(self):
148 response = self.app.post(url(controller='login', action='password_reset'),
200 response = self.app.post(url(controller='login', action='password_reset'),
149 {'email':'marcin@wrongmail.org', })
201 {'email':'marcin@wrongmail.org', })
150
202
151 assert "That e-mail address doesn't exist" in response.body, 'Missing error message about wrong email'
203 assert "That e-mail address doesn't exist" in response.body, 'Missing error message about wrong email'
152
204
153 def test_forgot_password(self):
205 def test_forgot_password(self):
154 response = self.app.get(url(controller='login', action='password_reset'))
206 response = self.app.get(url(controller='login', action='password_reset'))
155 assert response.status == '200 OK', 'Wrong response from login page got %s' % response.status
207 assert response.status == '200 OK', 'Wrong response from login page got %s' % response.status
156
208
157 username = 'test_password_reset_1'
209 username = 'test_password_reset_1'
158 password = 'qweqwe'
210 password = 'qweqwe'
159 email = 'marcin@python-works.com'
211 email = 'marcin@python-works.com'
160 name = 'passwd'
212 name = 'passwd'
161 lastname = 'reset'
213 lastname = 'reset'
162
214
163 response = self.app.post(url(controller='login', action='register'),
215 response = self.app.post(url(controller='login', action='register'),
164 {'username':username,
216 {'username':username,
165 'password':password,
217 'password':password,
166 'password_confirmation':password,
218 'password_confirmation':password,
167 'email':email,
219 'email':email,
168 'name':name,
220 'name':name,
169 'lastname':lastname})
221 'lastname':lastname})
170 #register new user for email test
222 #register new user for email test
171 response = self.app.post(url(controller='login', action='password_reset'),
223 response = self.app.post(url(controller='login', action='password_reset'),
172 {'email':email, })
224 {'email':email, })
173 print response.session['flash']
225 print response.session['flash']
174 assert 'You have successfully registered into rhodecode' in response.session['flash'][0], 'No flash message about user registration'
226 assert 'You have successfully registered into rhodecode' in response.session['flash'][0], 'No flash message about user registration'
175 assert 'Your new password was sent' in response.session['flash'][1], 'No flash message about password reset'
227 assert 'Your new password was sent' in response.session['flash'][1], 'No flash message about password reset'
176
228
177
229
178
230
General Comments 0
You need to be logged in to leave comments. Login now