##// END OF EJS Templates
fixed ldap tests when ldap lib is installed
marcink -
r3674:ff2ea58d beta
parent child Browse files
Show More
@@ -1,387 +1,384 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 import logging
22 import logging
23
23
24 import formencode
24 import formencode
25 from formencode import All
25 from formencode import All
26
26
27 from pylons.i18n.translation import _
27 from pylons.i18n.translation import _
28
28
29 from rhodecode.model import validators as v
29 from rhodecode.model import validators as v
30 from rhodecode import BACKENDS
30 from rhodecode import BACKENDS
31
31
32 log = logging.getLogger(__name__)
32 log = logging.getLogger(__name__)
33
33
34
34
35 class LoginForm(formencode.Schema):
35 class LoginForm(formencode.Schema):
36 allow_extra_fields = True
36 allow_extra_fields = True
37 filter_extra_fields = True
37 filter_extra_fields = True
38 username = v.UnicodeString(
38 username = v.UnicodeString(
39 strip=True,
39 strip=True,
40 min=1,
40 min=1,
41 not_empty=True,
41 not_empty=True,
42 messages={
42 messages={
43 'empty': _(u'Please enter a login'),
43 'empty': _(u'Please enter a login'),
44 'tooShort': _(u'Enter a value %(min)i characters long or more')}
44 'tooShort': _(u'Enter a value %(min)i characters long or more')}
45 )
45 )
46
46
47 password = v.UnicodeString(
47 password = v.UnicodeString(
48 strip=False,
48 strip=False,
49 min=3,
49 min=3,
50 not_empty=True,
50 not_empty=True,
51 messages={
51 messages={
52 'empty': _(u'Please enter a password'),
52 'empty': _(u'Please enter a password'),
53 'tooShort': _(u'Enter %(min)i characters or more')}
53 'tooShort': _(u'Enter %(min)i characters or more')}
54 )
54 )
55
55
56 remember = v.StringBoolean(if_missing=False)
56 remember = v.StringBoolean(if_missing=False)
57
57
58 chained_validators = [v.ValidAuth()]
58 chained_validators = [v.ValidAuth()]
59
59
60
60
61 def UserForm(edit=False, old_data={}):
61 def UserForm(edit=False, old_data={}):
62 class _UserForm(formencode.Schema):
62 class _UserForm(formencode.Schema):
63 allow_extra_fields = True
63 allow_extra_fields = True
64 filter_extra_fields = True
64 filter_extra_fields = True
65 username = All(v.UnicodeString(strip=True, min=1, not_empty=True),
65 username = All(v.UnicodeString(strip=True, min=1, not_empty=True),
66 v.ValidUsername(edit, old_data))
66 v.ValidUsername(edit, old_data))
67 if edit:
67 if edit:
68 new_password = All(
68 new_password = All(
69 v.ValidPassword(),
69 v.ValidPassword(),
70 v.UnicodeString(strip=False, min=6, not_empty=False)
70 v.UnicodeString(strip=False, min=6, not_empty=False)
71 )
71 )
72 password_confirmation = All(
72 password_confirmation = All(
73 v.ValidPassword(),
73 v.ValidPassword(),
74 v.UnicodeString(strip=False, min=6, not_empty=False),
74 v.UnicodeString(strip=False, min=6, not_empty=False),
75 )
75 )
76 admin = v.StringBoolean(if_missing=False)
76 admin = v.StringBoolean(if_missing=False)
77 else:
77 else:
78 password = All(
78 password = All(
79 v.ValidPassword(),
79 v.ValidPassword(),
80 v.UnicodeString(strip=False, min=6, not_empty=True)
80 v.UnicodeString(strip=False, min=6, not_empty=True)
81 )
81 )
82 password_confirmation = All(
82 password_confirmation = All(
83 v.ValidPassword(),
83 v.ValidPassword(),
84 v.UnicodeString(strip=False, min=6, not_empty=False)
84 v.UnicodeString(strip=False, min=6, not_empty=False)
85 )
85 )
86
86
87 active = v.StringBoolean(if_missing=False)
87 active = v.StringBoolean(if_missing=False)
88 firstname = v.UnicodeString(strip=True, min=1, not_empty=False)
88 firstname = v.UnicodeString(strip=True, min=1, not_empty=False)
89 lastname = v.UnicodeString(strip=True, min=1, not_empty=False)
89 lastname = v.UnicodeString(strip=True, min=1, not_empty=False)
90 email = All(v.Email(not_empty=True), v.UniqSystemEmail(old_data))
90 email = All(v.Email(not_empty=True), v.UniqSystemEmail(old_data))
91
91
92 chained_validators = [v.ValidPasswordsMatch()]
92 chained_validators = [v.ValidPasswordsMatch()]
93
93
94 return _UserForm
94 return _UserForm
95
95
96
96
97 def UserGroupForm(edit=False, old_data={}, available_members=[]):
97 def UserGroupForm(edit=False, old_data={}, available_members=[]):
98 class _UserGroupForm(formencode.Schema):
98 class _UserGroupForm(formencode.Schema):
99 allow_extra_fields = True
99 allow_extra_fields = True
100 filter_extra_fields = True
100 filter_extra_fields = True
101
101
102 users_group_name = All(
102 users_group_name = All(
103 v.UnicodeString(strip=True, min=1, not_empty=True),
103 v.UnicodeString(strip=True, min=1, not_empty=True),
104 v.ValidUserGroup(edit, old_data)
104 v.ValidUserGroup(edit, old_data)
105 )
105 )
106
106
107 users_group_active = v.StringBoolean(if_missing=False)
107 users_group_active = v.StringBoolean(if_missing=False)
108
108
109 if edit:
109 if edit:
110 users_group_members = v.OneOf(
110 users_group_members = v.OneOf(
111 available_members, hideList=False, testValueList=True,
111 available_members, hideList=False, testValueList=True,
112 if_missing=None, not_empty=False
112 if_missing=None, not_empty=False
113 )
113 )
114
114
115 return _UserGroupForm
115 return _UserGroupForm
116
116
117
117
118 def ReposGroupForm(edit=False, old_data={}, available_groups=[],
118 def ReposGroupForm(edit=False, old_data={}, available_groups=[],
119 can_create_in_root=False):
119 can_create_in_root=False):
120 class _ReposGroupForm(formencode.Schema):
120 class _ReposGroupForm(formencode.Schema):
121 allow_extra_fields = True
121 allow_extra_fields = True
122 filter_extra_fields = False
122 filter_extra_fields = False
123
123
124 group_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
124 group_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
125 v.SlugifyName())
125 v.SlugifyName())
126 group_description = v.UnicodeString(strip=True, min=1,
126 group_description = v.UnicodeString(strip=True, min=1,
127 not_empty=False)
127 not_empty=False)
128 if edit:
128 if edit:
129 #FIXME: do a special check that we cannot move a group to one of
129 #FIXME: do a special check that we cannot move a group to one of
130 #it's children
130 #it's children
131 pass
131 pass
132 group_parent_id = All(v.CanCreateGroup(can_create_in_root),
132 group_parent_id = All(v.CanCreateGroup(can_create_in_root),
133 v.OneOf(available_groups, hideList=False,
133 v.OneOf(available_groups, hideList=False,
134 testValueList=True,
134 testValueList=True,
135 if_missing=None, not_empty=True))
135 if_missing=None, not_empty=True))
136 enable_locking = v.StringBoolean(if_missing=False)
136 enable_locking = v.StringBoolean(if_missing=False)
137 recursive = v.StringBoolean(if_missing=False)
137 recursive = v.StringBoolean(if_missing=False)
138 chained_validators = [v.ValidReposGroup(edit, old_data),
138 chained_validators = [v.ValidReposGroup(edit, old_data),
139 v.ValidPerms('group')]
139 v.ValidPerms('group')]
140
140
141 return _ReposGroupForm
141 return _ReposGroupForm
142
142
143
143
144 def RegisterForm(edit=False, old_data={}):
144 def RegisterForm(edit=False, old_data={}):
145 class _RegisterForm(formencode.Schema):
145 class _RegisterForm(formencode.Schema):
146 allow_extra_fields = True
146 allow_extra_fields = True
147 filter_extra_fields = True
147 filter_extra_fields = True
148 username = All(
148 username = All(
149 v.ValidUsername(edit, old_data),
149 v.ValidUsername(edit, old_data),
150 v.UnicodeString(strip=True, min=1, not_empty=True)
150 v.UnicodeString(strip=True, min=1, not_empty=True)
151 )
151 )
152 password = All(
152 password = All(
153 v.ValidPassword(),
153 v.ValidPassword(),
154 v.UnicodeString(strip=False, min=6, not_empty=True)
154 v.UnicodeString(strip=False, min=6, not_empty=True)
155 )
155 )
156 password_confirmation = All(
156 password_confirmation = All(
157 v.ValidPassword(),
157 v.ValidPassword(),
158 v.UnicodeString(strip=False, min=6, not_empty=True)
158 v.UnicodeString(strip=False, min=6, not_empty=True)
159 )
159 )
160 active = v.StringBoolean(if_missing=False)
160 active = v.StringBoolean(if_missing=False)
161 firstname = v.UnicodeString(strip=True, min=1, not_empty=False)
161 firstname = v.UnicodeString(strip=True, min=1, not_empty=False)
162 lastname = v.UnicodeString(strip=True, min=1, not_empty=False)
162 lastname = v.UnicodeString(strip=True, min=1, not_empty=False)
163 email = All(v.Email(not_empty=True), v.UniqSystemEmail(old_data))
163 email = All(v.Email(not_empty=True), v.UniqSystemEmail(old_data))
164
164
165 chained_validators = [v.ValidPasswordsMatch()]
165 chained_validators = [v.ValidPasswordsMatch()]
166
166
167 return _RegisterForm
167 return _RegisterForm
168
168
169
169
170 def PasswordResetForm():
170 def PasswordResetForm():
171 class _PasswordResetForm(formencode.Schema):
171 class _PasswordResetForm(formencode.Schema):
172 allow_extra_fields = True
172 allow_extra_fields = True
173 filter_extra_fields = True
173 filter_extra_fields = True
174 email = All(v.ValidSystemEmail(), v.Email(not_empty=True))
174 email = All(v.ValidSystemEmail(), v.Email(not_empty=True))
175 return _PasswordResetForm
175 return _PasswordResetForm
176
176
177
177
178 def RepoForm(edit=False, old_data={}, supported_backends=BACKENDS.keys(),
178 def RepoForm(edit=False, old_data={}, supported_backends=BACKENDS.keys(),
179 repo_groups=[], landing_revs=[]):
179 repo_groups=[], landing_revs=[]):
180 class _RepoForm(formencode.Schema):
180 class _RepoForm(formencode.Schema):
181 allow_extra_fields = True
181 allow_extra_fields = True
182 filter_extra_fields = False
182 filter_extra_fields = False
183 repo_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
183 repo_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
184 v.SlugifyName())
184 v.SlugifyName())
185 repo_group = All(v.CanWriteGroup(old_data),
185 repo_group = All(v.CanWriteGroup(old_data),
186 v.OneOf(repo_groups, hideList=True))
186 v.OneOf(repo_groups, hideList=True))
187 repo_type = v.OneOf(supported_backends)
187 repo_type = v.OneOf(supported_backends)
188 repo_description = v.UnicodeString(strip=True, min=1, not_empty=False)
188 repo_description = v.UnicodeString(strip=True, min=1, not_empty=False)
189 repo_private = v.StringBoolean(if_missing=False)
189 repo_private = v.StringBoolean(if_missing=False)
190 repo_landing_rev = v.OneOf(landing_revs, hideList=True)
190 repo_landing_rev = v.OneOf(landing_revs, hideList=True)
191 clone_uri = All(v.UnicodeString(strip=True, min=1, not_empty=False))
191 clone_uri = All(v.UnicodeString(strip=True, min=1, not_empty=False))
192
192
193 repo_enable_statistics = v.StringBoolean(if_missing=False)
193 repo_enable_statistics = v.StringBoolean(if_missing=False)
194 repo_enable_downloads = v.StringBoolean(if_missing=False)
194 repo_enable_downloads = v.StringBoolean(if_missing=False)
195 repo_enable_locking = v.StringBoolean(if_missing=False)
195 repo_enable_locking = v.StringBoolean(if_missing=False)
196
196
197 if edit:
197 if edit:
198 #this is repo owner
198 #this is repo owner
199 user = All(v.UnicodeString(not_empty=True), v.ValidRepoUser())
199 user = All(v.UnicodeString(not_empty=True), v.ValidRepoUser())
200
200
201 chained_validators = [v.ValidCloneUri(),
201 chained_validators = [v.ValidCloneUri(),
202 v.ValidRepoName(edit, old_data)]
202 v.ValidRepoName(edit, old_data)]
203 return _RepoForm
203 return _RepoForm
204
204
205
205
206 def RepoPermsForm():
206 def RepoPermsForm():
207 class _RepoPermsForm(formencode.Schema):
207 class _RepoPermsForm(formencode.Schema):
208 allow_extra_fields = True
208 allow_extra_fields = True
209 filter_extra_fields = False
209 filter_extra_fields = False
210 chained_validators = [v.ValidPerms()]
210 chained_validators = [v.ValidPerms()]
211 return _RepoPermsForm
211 return _RepoPermsForm
212
212
213
213
214 def RepoFieldForm():
214 def RepoFieldForm():
215 class _RepoFieldForm(formencode.Schema):
215 class _RepoFieldForm(formencode.Schema):
216 filter_extra_fields = True
216 filter_extra_fields = True
217 allow_extra_fields = True
217 allow_extra_fields = True
218
218
219 new_field_key = All(v.FieldKey(),
219 new_field_key = All(v.FieldKey(),
220 v.UnicodeString(strip=True, min=3, not_empty=True))
220 v.UnicodeString(strip=True, min=3, not_empty=True))
221 new_field_value = v.UnicodeString(not_empty=False, if_missing='')
221 new_field_value = v.UnicodeString(not_empty=False, if_missing='')
222 new_field_type = v.OneOf(['str', 'unicode', 'list', 'tuple'],
222 new_field_type = v.OneOf(['str', 'unicode', 'list', 'tuple'],
223 if_missing='str')
223 if_missing='str')
224 new_field_label = v.UnicodeString(not_empty=False)
224 new_field_label = v.UnicodeString(not_empty=False)
225 new_field_desc = v.UnicodeString(not_empty=False)
225 new_field_desc = v.UnicodeString(not_empty=False)
226
226
227 return _RepoFieldForm
227 return _RepoFieldForm
228
228
229
229
230 def RepoForkForm(edit=False, old_data={}, supported_backends=BACKENDS.keys(),
230 def RepoForkForm(edit=False, old_data={}, supported_backends=BACKENDS.keys(),
231 repo_groups=[], landing_revs=[]):
231 repo_groups=[], landing_revs=[]):
232 class _RepoForkForm(formencode.Schema):
232 class _RepoForkForm(formencode.Schema):
233 allow_extra_fields = True
233 allow_extra_fields = True
234 filter_extra_fields = False
234 filter_extra_fields = False
235 repo_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
235 repo_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
236 v.SlugifyName())
236 v.SlugifyName())
237 repo_group = All(v.CanWriteGroup(),
237 repo_group = All(v.CanWriteGroup(),
238 v.OneOf(repo_groups, hideList=True))
238 v.OneOf(repo_groups, hideList=True))
239 repo_type = All(v.ValidForkType(old_data), v.OneOf(supported_backends))
239 repo_type = All(v.ValidForkType(old_data), v.OneOf(supported_backends))
240 description = v.UnicodeString(strip=True, min=1, not_empty=True)
240 description = v.UnicodeString(strip=True, min=1, not_empty=True)
241 private = v.StringBoolean(if_missing=False)
241 private = v.StringBoolean(if_missing=False)
242 copy_permissions = v.StringBoolean(if_missing=False)
242 copy_permissions = v.StringBoolean(if_missing=False)
243 update_after_clone = v.StringBoolean(if_missing=False)
243 update_after_clone = v.StringBoolean(if_missing=False)
244 fork_parent_id = v.UnicodeString()
244 fork_parent_id = v.UnicodeString()
245 chained_validators = [v.ValidForkName(edit, old_data)]
245 chained_validators = [v.ValidForkName(edit, old_data)]
246 landing_rev = v.OneOf(landing_revs, hideList=True)
246 landing_rev = v.OneOf(landing_revs, hideList=True)
247
247
248 return _RepoForkForm
248 return _RepoForkForm
249
249
250
250
251 def ApplicationSettingsForm():
251 def ApplicationSettingsForm():
252 class _ApplicationSettingsForm(formencode.Schema):
252 class _ApplicationSettingsForm(formencode.Schema):
253 allow_extra_fields = True
253 allow_extra_fields = True
254 filter_extra_fields = False
254 filter_extra_fields = False
255 rhodecode_title = v.UnicodeString(strip=True, min=1, not_empty=True)
255 rhodecode_title = v.UnicodeString(strip=True, min=1, not_empty=True)
256 rhodecode_realm = v.UnicodeString(strip=True, min=1, not_empty=True)
256 rhodecode_realm = v.UnicodeString(strip=True, min=1, not_empty=True)
257 rhodecode_ga_code = v.UnicodeString(strip=True, min=1, not_empty=False)
257 rhodecode_ga_code = v.UnicodeString(strip=True, min=1, not_empty=False)
258
258
259 return _ApplicationSettingsForm
259 return _ApplicationSettingsForm
260
260
261
261
262 def ApplicationVisualisationForm():
262 def ApplicationVisualisationForm():
263 class _ApplicationVisualisationForm(formencode.Schema):
263 class _ApplicationVisualisationForm(formencode.Schema):
264 allow_extra_fields = True
264 allow_extra_fields = True
265 filter_extra_fields = False
265 filter_extra_fields = False
266 rhodecode_show_public_icon = v.StringBoolean(if_missing=False)
266 rhodecode_show_public_icon = v.StringBoolean(if_missing=False)
267 rhodecode_show_private_icon = v.StringBoolean(if_missing=False)
267 rhodecode_show_private_icon = v.StringBoolean(if_missing=False)
268 rhodecode_stylify_metatags = v.StringBoolean(if_missing=False)
268 rhodecode_stylify_metatags = v.StringBoolean(if_missing=False)
269
269
270 rhodecode_lightweight_dashboard = v.StringBoolean(if_missing=False)
270 rhodecode_lightweight_dashboard = v.StringBoolean(if_missing=False)
271 rhodecode_repository_fields = v.StringBoolean(if_missing=False)
271 rhodecode_repository_fields = v.StringBoolean(if_missing=False)
272 rhodecode_lightweight_journal = v.StringBoolean(if_missing=False)
272 rhodecode_lightweight_journal = v.StringBoolean(if_missing=False)
273
273
274 return _ApplicationVisualisationForm
274 return _ApplicationVisualisationForm
275
275
276
276
277 def ApplicationUiSettingsForm():
277 def ApplicationUiSettingsForm():
278 class _ApplicationUiSettingsForm(formencode.Schema):
278 class _ApplicationUiSettingsForm(formencode.Schema):
279 allow_extra_fields = True
279 allow_extra_fields = True
280 filter_extra_fields = False
280 filter_extra_fields = False
281 web_push_ssl = v.StringBoolean(if_missing=False)
281 web_push_ssl = v.StringBoolean(if_missing=False)
282 paths_root_path = All(
282 paths_root_path = All(
283 v.ValidPath(),
283 v.ValidPath(),
284 v.UnicodeString(strip=True, min=1, not_empty=True)
284 v.UnicodeString(strip=True, min=1, not_empty=True)
285 )
285 )
286 hooks_changegroup_update = v.StringBoolean(if_missing=False)
286 hooks_changegroup_update = v.StringBoolean(if_missing=False)
287 hooks_changegroup_repo_size = v.StringBoolean(if_missing=False)
287 hooks_changegroup_repo_size = v.StringBoolean(if_missing=False)
288 hooks_changegroup_push_logger = v.StringBoolean(if_missing=False)
288 hooks_changegroup_push_logger = v.StringBoolean(if_missing=False)
289 hooks_outgoing_pull_logger = v.StringBoolean(if_missing=False)
289 hooks_outgoing_pull_logger = v.StringBoolean(if_missing=False)
290
290
291 extensions_largefiles = v.StringBoolean(if_missing=False)
291 extensions_largefiles = v.StringBoolean(if_missing=False)
292 extensions_hgsubversion = v.StringBoolean(if_missing=False)
292 extensions_hgsubversion = v.StringBoolean(if_missing=False)
293 extensions_hggit = v.StringBoolean(if_missing=False)
293 extensions_hggit = v.StringBoolean(if_missing=False)
294
294
295 return _ApplicationUiSettingsForm
295 return _ApplicationUiSettingsForm
296
296
297
297
298 def DefaultPermissionsForm(repo_perms_choices, group_perms_choices,
298 def DefaultPermissionsForm(repo_perms_choices, group_perms_choices,
299 register_choices, create_choices, fork_choices):
299 register_choices, create_choices, fork_choices):
300 class _DefaultPermissionsForm(formencode.Schema):
300 class _DefaultPermissionsForm(formencode.Schema):
301 allow_extra_fields = True
301 allow_extra_fields = True
302 filter_extra_fields = True
302 filter_extra_fields = True
303 overwrite_default_repo = v.StringBoolean(if_missing=False)
303 overwrite_default_repo = v.StringBoolean(if_missing=False)
304 overwrite_default_group = v.StringBoolean(if_missing=False)
304 overwrite_default_group = v.StringBoolean(if_missing=False)
305 anonymous = v.StringBoolean(if_missing=False)
305 anonymous = v.StringBoolean(if_missing=False)
306 default_repo_perm = v.OneOf(repo_perms_choices)
306 default_repo_perm = v.OneOf(repo_perms_choices)
307 default_group_perm = v.OneOf(group_perms_choices)
307 default_group_perm = v.OneOf(group_perms_choices)
308 default_register = v.OneOf(register_choices)
308 default_register = v.OneOf(register_choices)
309 default_create = v.OneOf(create_choices)
309 default_create = v.OneOf(create_choices)
310 default_fork = v.OneOf(fork_choices)
310 default_fork = v.OneOf(fork_choices)
311
311
312 return _DefaultPermissionsForm
312 return _DefaultPermissionsForm
313
313
314
314
315 def DefaultsForm(edit=False, old_data={}, supported_backends=BACKENDS.keys()):
315 def DefaultsForm(edit=False, old_data={}, supported_backends=BACKENDS.keys()):
316 class _DefaultsForm(formencode.Schema):
316 class _DefaultsForm(formencode.Schema):
317 allow_extra_fields = True
317 allow_extra_fields = True
318 filter_extra_fields = True
318 filter_extra_fields = True
319 default_repo_type = v.OneOf(supported_backends)
319 default_repo_type = v.OneOf(supported_backends)
320 default_repo_private = v.StringBoolean(if_missing=False)
320 default_repo_private = v.StringBoolean(if_missing=False)
321 default_repo_enable_statistics = v.StringBoolean(if_missing=False)
321 default_repo_enable_statistics = v.StringBoolean(if_missing=False)
322 default_repo_enable_downloads = v.StringBoolean(if_missing=False)
322 default_repo_enable_downloads = v.StringBoolean(if_missing=False)
323 default_repo_enable_locking = v.StringBoolean(if_missing=False)
323 default_repo_enable_locking = v.StringBoolean(if_missing=False)
324
324
325 return _DefaultsForm
325 return _DefaultsForm
326
326
327
327
328 def LdapSettingsForm(tls_reqcert_choices, search_scope_choices,
328 def LdapSettingsForm(tls_reqcert_choices, search_scope_choices,
329 tls_kind_choices):
329 tls_kind_choices):
330 class _LdapSettingsForm(formencode.Schema):
330 class _LdapSettingsForm(formencode.Schema):
331 allow_extra_fields = True
331 allow_extra_fields = True
332 filter_extra_fields = True
332 filter_extra_fields = True
333 #pre_validators = [LdapLibValidator]
333 #pre_validators = [LdapLibValidator]
334 ldap_active = v.StringBoolean(if_missing=False)
334 ldap_active = v.StringBoolean(if_missing=False)
335 ldap_host = v.UnicodeString(strip=True,)
335 ldap_host = v.UnicodeString(strip=True,)
336 ldap_port = v.Number(strip=True,)
336 ldap_port = v.Number(strip=True,)
337 ldap_tls_kind = v.OneOf(tls_kind_choices)
337 ldap_tls_kind = v.OneOf(tls_kind_choices)
338 ldap_tls_reqcert = v.OneOf(tls_reqcert_choices)
338 ldap_tls_reqcert = v.OneOf(tls_reqcert_choices)
339 ldap_dn_user = v.UnicodeString(strip=True,)
339 ldap_dn_user = v.UnicodeString(strip=True,)
340 ldap_dn_pass = v.UnicodeString(strip=True,)
340 ldap_dn_pass = v.UnicodeString(strip=True,)
341 ldap_base_dn = v.UnicodeString(strip=True,)
341 ldap_base_dn = v.UnicodeString(strip=True,)
342 ldap_filter = v.UnicodeString(strip=True,)
342 ldap_filter = v.UnicodeString(strip=True,)
343 ldap_search_scope = v.OneOf(search_scope_choices)
343 ldap_search_scope = v.OneOf(search_scope_choices)
344 ldap_attr_login = All(
344 ldap_attr_login = v.AttrLoginValidator()(not_empty=True)
345 v.AttrLoginValidator(),
346 v.UnicodeString(strip=True,)
347 )
348 ldap_attr_firstname = v.UnicodeString(strip=True,)
345 ldap_attr_firstname = v.UnicodeString(strip=True,)
349 ldap_attr_lastname = v.UnicodeString(strip=True,)
346 ldap_attr_lastname = v.UnicodeString(strip=True,)
350 ldap_attr_email = v.UnicodeString(strip=True,)
347 ldap_attr_email = v.UnicodeString(strip=True,)
351
348
352 return _LdapSettingsForm
349 return _LdapSettingsForm
353
350
354
351
355 def UserExtraEmailForm():
352 def UserExtraEmailForm():
356 class _UserExtraEmailForm(formencode.Schema):
353 class _UserExtraEmailForm(formencode.Schema):
357 email = All(v.UniqSystemEmail(), v.Email(not_empty=True))
354 email = All(v.UniqSystemEmail(), v.Email(not_empty=True))
358 return _UserExtraEmailForm
355 return _UserExtraEmailForm
359
356
360
357
361 def UserExtraIpForm():
358 def UserExtraIpForm():
362 class _UserExtraIpForm(formencode.Schema):
359 class _UserExtraIpForm(formencode.Schema):
363 ip = v.ValidIp()(not_empty=True)
360 ip = v.ValidIp()(not_empty=True)
364 return _UserExtraIpForm
361 return _UserExtraIpForm
365
362
366
363
367 def PullRequestForm(repo_id):
364 def PullRequestForm(repo_id):
368 class _PullRequestForm(formencode.Schema):
365 class _PullRequestForm(formencode.Schema):
369 allow_extra_fields = True
366 allow_extra_fields = True
370 filter_extra_fields = True
367 filter_extra_fields = True
371
368
372 user = v.UnicodeString(strip=True, required=True)
369 user = v.UnicodeString(strip=True, required=True)
373 org_repo = v.UnicodeString(strip=True, required=True)
370 org_repo = v.UnicodeString(strip=True, required=True)
374 org_ref = v.UnicodeString(strip=True, required=True)
371 org_ref = v.UnicodeString(strip=True, required=True)
375 other_repo = v.UnicodeString(strip=True, required=True)
372 other_repo = v.UnicodeString(strip=True, required=True)
376 other_ref = v.UnicodeString(strip=True, required=True)
373 other_ref = v.UnicodeString(strip=True, required=True)
377 revisions = All(#v.NotReviewedRevisions(repo_id)(),
374 revisions = All(#v.NotReviewedRevisions(repo_id)(),
378 v.UniqueList(not_empty=True))
375 v.UniqueList(not_empty=True))
379 review_members = v.UniqueList(not_empty=True)
376 review_members = v.UniqueList(not_empty=True)
380
377
381 pullrequest_title = v.UnicodeString(strip=True, required=True, min=3)
378 pullrequest_title = v.UnicodeString(strip=True, required=True, min=3)
382 pullrequest_desc = v.UnicodeString(strip=True, required=False)
379 pullrequest_desc = v.UnicodeString(strip=True, required=False)
383
380
384 ancestor_rev = v.UnicodeString(strip=True, required=True)
381 ancestor_rev = v.UnicodeString(strip=True, required=True)
385 merge_rev = v.UnicodeString(strip=True, required=True)
382 merge_rev = v.UnicodeString(strip=True, required=True)
386
383
387 return _PullRequestForm
384 return _PullRequestForm
@@ -1,813 +1,807 b''
1 """
1 """
2 Set of generic validators
2 Set of generic validators
3 """
3 """
4 import os
4 import os
5 import re
5 import re
6 import formencode
6 import formencode
7 import logging
7 import logging
8 from collections import defaultdict
8 from collections import defaultdict
9 from pylons.i18n.translation import _
9 from pylons.i18n.translation import _
10 from webhelpers.pylonslib.secure_form import authentication_token
10 from webhelpers.pylonslib.secure_form import authentication_token
11
11
12 from formencode.validators import (
12 from formencode.validators import (
13 UnicodeString, OneOf, Int, Number, Regex, Email, Bool, StringBoolean, Set,
13 UnicodeString, OneOf, Int, Number, Regex, Email, Bool, StringBoolean, Set,
14 NotEmpty, IPAddress, CIDR
14 NotEmpty, IPAddress, CIDR
15 )
15 )
16 from rhodecode.lib.compat import OrderedSet
16 from rhodecode.lib.compat import OrderedSet
17 from rhodecode.lib import ipaddr
17 from rhodecode.lib import ipaddr
18 from rhodecode.lib.utils import repo_name_slug
18 from rhodecode.lib.utils import repo_name_slug
19 from rhodecode.lib.utils2 import safe_int, str2bool
19 from rhodecode.lib.utils2 import safe_int, str2bool
20 from rhodecode.model.db import RepoGroup, Repository, UserGroup, User,\
20 from rhodecode.model.db import RepoGroup, Repository, UserGroup, User,\
21 ChangesetStatus
21 ChangesetStatus
22 from rhodecode.lib.exceptions import LdapImportError
22 from rhodecode.lib.exceptions import LdapImportError
23 from rhodecode.config.routing import ADMIN_PREFIX
23 from rhodecode.config.routing import ADMIN_PREFIX
24 from rhodecode.lib.auth import HasReposGroupPermissionAny, HasPermissionAny
24 from rhodecode.lib.auth import HasReposGroupPermissionAny, HasPermissionAny
25
25
26 # silence warnings and pylint
26 # silence warnings and pylint
27 UnicodeString, OneOf, Int, Number, Regex, Email, Bool, StringBoolean, Set, \
27 UnicodeString, OneOf, Int, Number, Regex, Email, Bool, StringBoolean, Set, \
28 NotEmpty, IPAddress, CIDR
28 NotEmpty, IPAddress, CIDR
29
29
30 log = logging.getLogger(__name__)
30 log = logging.getLogger(__name__)
31
31
32
32
33 class UniqueList(formencode.FancyValidator):
33 class UniqueList(formencode.FancyValidator):
34 """
34 """
35 Unique List !
35 Unique List !
36 """
36 """
37 messages = dict(
37 messages = dict(
38 empty=_('Value cannot be an empty list'),
38 empty=_('Value cannot be an empty list'),
39 missing_value=_('Value cannot be an empty list'),
39 missing_value=_('Value cannot be an empty list'),
40 )
40 )
41
41
42 def _to_python(self, value, state):
42 def _to_python(self, value, state):
43 if isinstance(value, list):
43 if isinstance(value, list):
44 return value
44 return value
45 elif isinstance(value, set):
45 elif isinstance(value, set):
46 return list(value)
46 return list(value)
47 elif isinstance(value, tuple):
47 elif isinstance(value, tuple):
48 return list(value)
48 return list(value)
49 elif value is None:
49 elif value is None:
50 return []
50 return []
51 else:
51 else:
52 return [value]
52 return [value]
53
53
54 def empty_value(self, value):
54 def empty_value(self, value):
55 return []
55 return []
56
56
57
57
58 class StateObj(object):
58 class StateObj(object):
59 """
59 """
60 this is needed to translate the messages using _() in validators
60 this is needed to translate the messages using _() in validators
61 """
61 """
62 _ = staticmethod(_)
62 _ = staticmethod(_)
63
63
64
64
65 def M(self, key, state=None, **kwargs):
65 def M(self, key, state=None, **kwargs):
66 """
66 """
67 returns string from self.message based on given key,
67 returns string from self.message based on given key,
68 passed kw params are used to substitute %(named)s params inside
68 passed kw params are used to substitute %(named)s params inside
69 translated strings
69 translated strings
70
70
71 :param msg:
71 :param msg:
72 :param state:
72 :param state:
73 """
73 """
74 if state is None:
74 if state is None:
75 state = StateObj()
75 state = StateObj()
76 else:
76 else:
77 state._ = staticmethod(_)
77 state._ = staticmethod(_)
78 #inject validator into state object
78 #inject validator into state object
79 return self.message(key, state, **kwargs)
79 return self.message(key, state, **kwargs)
80
80
81
81
82 def ValidUsername(edit=False, old_data={}):
82 def ValidUsername(edit=False, old_data={}):
83 class _validator(formencode.validators.FancyValidator):
83 class _validator(formencode.validators.FancyValidator):
84 messages = {
84 messages = {
85 'username_exists': _(u'Username "%(username)s" already exists'),
85 'username_exists': _(u'Username "%(username)s" already exists'),
86 'system_invalid_username':
86 'system_invalid_username':
87 _(u'Username "%(username)s" is forbidden'),
87 _(u'Username "%(username)s" is forbidden'),
88 'invalid_username':
88 'invalid_username':
89 _(u'Username may only contain alphanumeric characters '
89 _(u'Username may only contain alphanumeric characters '
90 'underscores, periods or dashes and must begin with '
90 'underscores, periods or dashes and must begin with '
91 'alphanumeric character')
91 'alphanumeric character')
92 }
92 }
93
93
94 def validate_python(self, value, state):
94 def validate_python(self, value, state):
95 if value in ['default', 'new_user']:
95 if value in ['default', 'new_user']:
96 msg = M(self, 'system_invalid_username', state, username=value)
96 msg = M(self, 'system_invalid_username', state, username=value)
97 raise formencode.Invalid(msg, value, state)
97 raise formencode.Invalid(msg, value, state)
98 #check if user is unique
98 #check if user is unique
99 old_un = None
99 old_un = None
100 if edit:
100 if edit:
101 old_un = User.get(old_data.get('user_id')).username
101 old_un = User.get(old_data.get('user_id')).username
102
102
103 if old_un != value or not edit:
103 if old_un != value or not edit:
104 if User.get_by_username(value, case_insensitive=True):
104 if User.get_by_username(value, case_insensitive=True):
105 msg = M(self, 'username_exists', state, username=value)
105 msg = M(self, 'username_exists', state, username=value)
106 raise formencode.Invalid(msg, value, state)
106 raise formencode.Invalid(msg, value, state)
107
107
108 if re.match(r'^[a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]*$', value) is None:
108 if re.match(r'^[a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]*$', value) is None:
109 msg = M(self, 'invalid_username', state)
109 msg = M(self, 'invalid_username', state)
110 raise formencode.Invalid(msg, value, state)
110 raise formencode.Invalid(msg, value, state)
111 return _validator
111 return _validator
112
112
113
113
114 def ValidRepoUser():
114 def ValidRepoUser():
115 class _validator(formencode.validators.FancyValidator):
115 class _validator(formencode.validators.FancyValidator):
116 messages = {
116 messages = {
117 'invalid_username': _(u'Username %(username)s is not valid')
117 'invalid_username': _(u'Username %(username)s is not valid')
118 }
118 }
119
119
120 def validate_python(self, value, state):
120 def validate_python(self, value, state):
121 try:
121 try:
122 User.query().filter(User.active == True)\
122 User.query().filter(User.active == True)\
123 .filter(User.username == value).one()
123 .filter(User.username == value).one()
124 except Exception:
124 except Exception:
125 msg = M(self, 'invalid_username', state, username=value)
125 msg = M(self, 'invalid_username', state, username=value)
126 raise formencode.Invalid(msg, value, state,
126 raise formencode.Invalid(msg, value, state,
127 error_dict=dict(username=msg)
127 error_dict=dict(username=msg)
128 )
128 )
129
129
130 return _validator
130 return _validator
131
131
132
132
133 def ValidUserGroup(edit=False, old_data={}):
133 def ValidUserGroup(edit=False, old_data={}):
134 class _validator(formencode.validators.FancyValidator):
134 class _validator(formencode.validators.FancyValidator):
135 messages = {
135 messages = {
136 'invalid_group': _(u'Invalid user group name'),
136 'invalid_group': _(u'Invalid user group name'),
137 'group_exist': _(u'User group "%(usergroup)s" already exists'),
137 'group_exist': _(u'User group "%(usergroup)s" already exists'),
138 'invalid_usergroup_name':
138 'invalid_usergroup_name':
139 _(u'user group name may only contain alphanumeric '
139 _(u'user group name may only contain alphanumeric '
140 'characters underscores, periods or dashes and must begin '
140 'characters underscores, periods or dashes and must begin '
141 'with alphanumeric character')
141 'with alphanumeric character')
142 }
142 }
143
143
144 def validate_python(self, value, state):
144 def validate_python(self, value, state):
145 if value in ['default']:
145 if value in ['default']:
146 msg = M(self, 'invalid_group', state)
146 msg = M(self, 'invalid_group', state)
147 raise formencode.Invalid(msg, value, state,
147 raise formencode.Invalid(msg, value, state,
148 error_dict=dict(users_group_name=msg)
148 error_dict=dict(users_group_name=msg)
149 )
149 )
150 #check if group is unique
150 #check if group is unique
151 old_ugname = None
151 old_ugname = None
152 if edit:
152 if edit:
153 old_id = old_data.get('users_group_id')
153 old_id = old_data.get('users_group_id')
154 old_ugname = UserGroup.get(old_id).users_group_name
154 old_ugname = UserGroup.get(old_id).users_group_name
155
155
156 if old_ugname != value or not edit:
156 if old_ugname != value or not edit:
157 is_existing_group = UserGroup.get_by_group_name(value,
157 is_existing_group = UserGroup.get_by_group_name(value,
158 case_insensitive=True)
158 case_insensitive=True)
159 if is_existing_group:
159 if is_existing_group:
160 msg = M(self, 'group_exist', state, usergroup=value)
160 msg = M(self, 'group_exist', state, usergroup=value)
161 raise formencode.Invalid(msg, value, state,
161 raise formencode.Invalid(msg, value, state,
162 error_dict=dict(users_group_name=msg)
162 error_dict=dict(users_group_name=msg)
163 )
163 )
164
164
165 if re.match(r'^[a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]+$', value) is None:
165 if re.match(r'^[a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]+$', value) is None:
166 msg = M(self, 'invalid_usergroup_name', state)
166 msg = M(self, 'invalid_usergroup_name', state)
167 raise formencode.Invalid(msg, value, state,
167 raise formencode.Invalid(msg, value, state,
168 error_dict=dict(users_group_name=msg)
168 error_dict=dict(users_group_name=msg)
169 )
169 )
170
170
171 return _validator
171 return _validator
172
172
173
173
174 def ValidReposGroup(edit=False, old_data={}):
174 def ValidReposGroup(edit=False, old_data={}):
175 class _validator(formencode.validators.FancyValidator):
175 class _validator(formencode.validators.FancyValidator):
176 messages = {
176 messages = {
177 'group_parent_id': _(u'Cannot assign this group as parent'),
177 'group_parent_id': _(u'Cannot assign this group as parent'),
178 'group_exists': _(u'Group "%(group_name)s" already exists'),
178 'group_exists': _(u'Group "%(group_name)s" already exists'),
179 'repo_exists':
179 'repo_exists':
180 _(u'Repository with name "%(group_name)s" already exists')
180 _(u'Repository with name "%(group_name)s" already exists')
181 }
181 }
182
182
183 def validate_python(self, value, state):
183 def validate_python(self, value, state):
184 # TODO WRITE VALIDATIONS
184 # TODO WRITE VALIDATIONS
185 group_name = value.get('group_name')
185 group_name = value.get('group_name')
186 group_parent_id = value.get('group_parent_id')
186 group_parent_id = value.get('group_parent_id')
187
187
188 # slugify repo group just in case :)
188 # slugify repo group just in case :)
189 slug = repo_name_slug(group_name)
189 slug = repo_name_slug(group_name)
190
190
191 # check for parent of self
191 # check for parent of self
192 parent_of_self = lambda: (
192 parent_of_self = lambda: (
193 old_data['group_id'] == int(group_parent_id)
193 old_data['group_id'] == int(group_parent_id)
194 if group_parent_id else False
194 if group_parent_id else False
195 )
195 )
196 if edit and parent_of_self():
196 if edit and parent_of_self():
197 msg = M(self, 'group_parent_id', state)
197 msg = M(self, 'group_parent_id', state)
198 raise formencode.Invalid(msg, value, state,
198 raise formencode.Invalid(msg, value, state,
199 error_dict=dict(group_parent_id=msg)
199 error_dict=dict(group_parent_id=msg)
200 )
200 )
201
201
202 old_gname = None
202 old_gname = None
203 if edit:
203 if edit:
204 old_gname = RepoGroup.get(old_data.get('group_id')).group_name
204 old_gname = RepoGroup.get(old_data.get('group_id')).group_name
205
205
206 if old_gname != group_name or not edit:
206 if old_gname != group_name or not edit:
207
207
208 # check group
208 # check group
209 gr = RepoGroup.query()\
209 gr = RepoGroup.query()\
210 .filter(RepoGroup.group_name == slug)\
210 .filter(RepoGroup.group_name == slug)\
211 .filter(RepoGroup.group_parent_id == group_parent_id)\
211 .filter(RepoGroup.group_parent_id == group_parent_id)\
212 .scalar()
212 .scalar()
213
213
214 if gr:
214 if gr:
215 msg = M(self, 'group_exists', state, group_name=slug)
215 msg = M(self, 'group_exists', state, group_name=slug)
216 raise formencode.Invalid(msg, value, state,
216 raise formencode.Invalid(msg, value, state,
217 error_dict=dict(group_name=msg)
217 error_dict=dict(group_name=msg)
218 )
218 )
219
219
220 # check for same repo
220 # check for same repo
221 repo = Repository.query()\
221 repo = Repository.query()\
222 .filter(Repository.repo_name == slug)\
222 .filter(Repository.repo_name == slug)\
223 .scalar()
223 .scalar()
224
224
225 if repo:
225 if repo:
226 msg = M(self, 'repo_exists', state, group_name=slug)
226 msg = M(self, 'repo_exists', state, group_name=slug)
227 raise formencode.Invalid(msg, value, state,
227 raise formencode.Invalid(msg, value, state,
228 error_dict=dict(group_name=msg)
228 error_dict=dict(group_name=msg)
229 )
229 )
230
230
231 return _validator
231 return _validator
232
232
233
233
234 def ValidPassword():
234 def ValidPassword():
235 class _validator(formencode.validators.FancyValidator):
235 class _validator(formencode.validators.FancyValidator):
236 messages = {
236 messages = {
237 'invalid_password':
237 'invalid_password':
238 _(u'Invalid characters (non-ascii) in password')
238 _(u'Invalid characters (non-ascii) in password')
239 }
239 }
240
240
241 def validate_python(self, value, state):
241 def validate_python(self, value, state):
242 try:
242 try:
243 (value or '').decode('ascii')
243 (value or '').decode('ascii')
244 except UnicodeError:
244 except UnicodeError:
245 msg = M(self, 'invalid_password', state)
245 msg = M(self, 'invalid_password', state)
246 raise formencode.Invalid(msg, value, state,)
246 raise formencode.Invalid(msg, value, state,)
247 return _validator
247 return _validator
248
248
249
249
250 def ValidPasswordsMatch():
250 def ValidPasswordsMatch():
251 class _validator(formencode.validators.FancyValidator):
251 class _validator(formencode.validators.FancyValidator):
252 messages = {
252 messages = {
253 'password_mismatch': _(u'Passwords do not match'),
253 'password_mismatch': _(u'Passwords do not match'),
254 }
254 }
255
255
256 def validate_python(self, value, state):
256 def validate_python(self, value, state):
257
257
258 pass_val = value.get('password') or value.get('new_password')
258 pass_val = value.get('password') or value.get('new_password')
259 if pass_val != value['password_confirmation']:
259 if pass_val != value['password_confirmation']:
260 msg = M(self, 'password_mismatch', state)
260 msg = M(self, 'password_mismatch', state)
261 raise formencode.Invalid(msg, value, state,
261 raise formencode.Invalid(msg, value, state,
262 error_dict=dict(password_confirmation=msg)
262 error_dict=dict(password_confirmation=msg)
263 )
263 )
264 return _validator
264 return _validator
265
265
266
266
267 def ValidAuth():
267 def ValidAuth():
268 class _validator(formencode.validators.FancyValidator):
268 class _validator(formencode.validators.FancyValidator):
269 messages = {
269 messages = {
270 'invalid_password': _(u'invalid password'),
270 'invalid_password': _(u'invalid password'),
271 'invalid_username': _(u'invalid user name'),
271 'invalid_username': _(u'invalid user name'),
272 'disabled_account': _(u'Your account is disabled')
272 'disabled_account': _(u'Your account is disabled')
273 }
273 }
274
274
275 def validate_python(self, value, state):
275 def validate_python(self, value, state):
276 from rhodecode.lib.auth import authenticate
276 from rhodecode.lib.auth import authenticate
277
277
278 password = value['password']
278 password = value['password']
279 username = value['username']
279 username = value['username']
280
280
281 if not authenticate(username, password):
281 if not authenticate(username, password):
282 user = User.get_by_username(username)
282 user = User.get_by_username(username)
283 if user and not user.active:
283 if user and not user.active:
284 log.warning('user %s is disabled' % username)
284 log.warning('user %s is disabled' % username)
285 msg = M(self, 'disabled_account', state)
285 msg = M(self, 'disabled_account', state)
286 raise formencode.Invalid(msg, value, state,
286 raise formencode.Invalid(msg, value, state,
287 error_dict=dict(username=msg)
287 error_dict=dict(username=msg)
288 )
288 )
289 else:
289 else:
290 log.warning('user %s failed to authenticate' % username)
290 log.warning('user %s failed to authenticate' % username)
291 msg = M(self, 'invalid_username', state)
291 msg = M(self, 'invalid_username', state)
292 msg2 = M(self, 'invalid_password', state)
292 msg2 = M(self, 'invalid_password', state)
293 raise formencode.Invalid(msg, value, state,
293 raise formencode.Invalid(msg, value, state,
294 error_dict=dict(username=msg, password=msg2)
294 error_dict=dict(username=msg, password=msg2)
295 )
295 )
296 return _validator
296 return _validator
297
297
298
298
299 def ValidAuthToken():
299 def ValidAuthToken():
300 class _validator(formencode.validators.FancyValidator):
300 class _validator(formencode.validators.FancyValidator):
301 messages = {
301 messages = {
302 'invalid_token': _(u'Token mismatch')
302 'invalid_token': _(u'Token mismatch')
303 }
303 }
304
304
305 def validate_python(self, value, state):
305 def validate_python(self, value, state):
306 if value != authentication_token():
306 if value != authentication_token():
307 msg = M(self, 'invalid_token', state)
307 msg = M(self, 'invalid_token', state)
308 raise formencode.Invalid(msg, value, state)
308 raise formencode.Invalid(msg, value, state)
309 return _validator
309 return _validator
310
310
311
311
312 def ValidRepoName(edit=False, old_data={}):
312 def ValidRepoName(edit=False, old_data={}):
313 class _validator(formencode.validators.FancyValidator):
313 class _validator(formencode.validators.FancyValidator):
314 messages = {
314 messages = {
315 'invalid_repo_name':
315 'invalid_repo_name':
316 _(u'Repository name %(repo)s is disallowed'),
316 _(u'Repository name %(repo)s is disallowed'),
317 'repository_exists':
317 'repository_exists':
318 _(u'Repository named %(repo)s already exists'),
318 _(u'Repository named %(repo)s already exists'),
319 'repository_in_group_exists': _(u'Repository "%(repo)s" already '
319 'repository_in_group_exists': _(u'Repository "%(repo)s" already '
320 'exists in group "%(group)s"'),
320 'exists in group "%(group)s"'),
321 'same_group_exists': _(u'Repository group with name "%(repo)s" '
321 'same_group_exists': _(u'Repository group with name "%(repo)s" '
322 'already exists')
322 'already exists')
323 }
323 }
324
324
325 def _to_python(self, value, state):
325 def _to_python(self, value, state):
326 repo_name = repo_name_slug(value.get('repo_name', ''))
326 repo_name = repo_name_slug(value.get('repo_name', ''))
327 repo_group = value.get('repo_group')
327 repo_group = value.get('repo_group')
328 if repo_group:
328 if repo_group:
329 gr = RepoGroup.get(repo_group)
329 gr = RepoGroup.get(repo_group)
330 group_path = gr.full_path
330 group_path = gr.full_path
331 group_name = gr.group_name
331 group_name = gr.group_name
332 # value needs to be aware of group name in order to check
332 # value needs to be aware of group name in order to check
333 # db key This is an actual just the name to store in the
333 # db key This is an actual just the name to store in the
334 # database
334 # database
335 repo_name_full = group_path + RepoGroup.url_sep() + repo_name
335 repo_name_full = group_path + RepoGroup.url_sep() + repo_name
336 else:
336 else:
337 group_name = group_path = ''
337 group_name = group_path = ''
338 repo_name_full = repo_name
338 repo_name_full = repo_name
339
339
340 value['repo_name'] = repo_name
340 value['repo_name'] = repo_name
341 value['repo_name_full'] = repo_name_full
341 value['repo_name_full'] = repo_name_full
342 value['group_path'] = group_path
342 value['group_path'] = group_path
343 value['group_name'] = group_name
343 value['group_name'] = group_name
344 return value
344 return value
345
345
346 def validate_python(self, value, state):
346 def validate_python(self, value, state):
347
347
348 repo_name = value.get('repo_name')
348 repo_name = value.get('repo_name')
349 repo_name_full = value.get('repo_name_full')
349 repo_name_full = value.get('repo_name_full')
350 group_path = value.get('group_path')
350 group_path = value.get('group_path')
351 group_name = value.get('group_name')
351 group_name = value.get('group_name')
352
352
353 if repo_name in [ADMIN_PREFIX, '']:
353 if repo_name in [ADMIN_PREFIX, '']:
354 msg = M(self, 'invalid_repo_name', state, repo=repo_name)
354 msg = M(self, 'invalid_repo_name', state, repo=repo_name)
355 raise formencode.Invalid(msg, value, state,
355 raise formencode.Invalid(msg, value, state,
356 error_dict=dict(repo_name=msg)
356 error_dict=dict(repo_name=msg)
357 )
357 )
358
358
359 rename = old_data.get('repo_name') != repo_name_full
359 rename = old_data.get('repo_name') != repo_name_full
360 create = not edit
360 create = not edit
361 if rename or create:
361 if rename or create:
362
362
363 if group_path != '':
363 if group_path != '':
364 if Repository.get_by_repo_name(repo_name_full):
364 if Repository.get_by_repo_name(repo_name_full):
365 msg = M(self, 'repository_in_group_exists', state,
365 msg = M(self, 'repository_in_group_exists', state,
366 repo=repo_name, group=group_name)
366 repo=repo_name, group=group_name)
367 raise formencode.Invalid(msg, value, state,
367 raise formencode.Invalid(msg, value, state,
368 error_dict=dict(repo_name=msg)
368 error_dict=dict(repo_name=msg)
369 )
369 )
370 elif RepoGroup.get_by_group_name(repo_name_full):
370 elif RepoGroup.get_by_group_name(repo_name_full):
371 msg = M(self, 'same_group_exists', state,
371 msg = M(self, 'same_group_exists', state,
372 repo=repo_name)
372 repo=repo_name)
373 raise formencode.Invalid(msg, value, state,
373 raise formencode.Invalid(msg, value, state,
374 error_dict=dict(repo_name=msg)
374 error_dict=dict(repo_name=msg)
375 )
375 )
376
376
377 elif Repository.get_by_repo_name(repo_name_full):
377 elif Repository.get_by_repo_name(repo_name_full):
378 msg = M(self, 'repository_exists', state,
378 msg = M(self, 'repository_exists', state,
379 repo=repo_name)
379 repo=repo_name)
380 raise formencode.Invalid(msg, value, state,
380 raise formencode.Invalid(msg, value, state,
381 error_dict=dict(repo_name=msg)
381 error_dict=dict(repo_name=msg)
382 )
382 )
383 return value
383 return value
384 return _validator
384 return _validator
385
385
386
386
387 def ValidForkName(*args, **kwargs):
387 def ValidForkName(*args, **kwargs):
388 return ValidRepoName(*args, **kwargs)
388 return ValidRepoName(*args, **kwargs)
389
389
390
390
391 def SlugifyName():
391 def SlugifyName():
392 class _validator(formencode.validators.FancyValidator):
392 class _validator(formencode.validators.FancyValidator):
393
393
394 def _to_python(self, value, state):
394 def _to_python(self, value, state):
395 return repo_name_slug(value)
395 return repo_name_slug(value)
396
396
397 def validate_python(self, value, state):
397 def validate_python(self, value, state):
398 pass
398 pass
399
399
400 return _validator
400 return _validator
401
401
402
402
403 def ValidCloneUri():
403 def ValidCloneUri():
404 from rhodecode.lib.utils import make_ui
404 from rhodecode.lib.utils import make_ui
405
405
406 def url_handler(repo_type, url, ui=None):
406 def url_handler(repo_type, url, ui=None):
407 if repo_type == 'hg':
407 if repo_type == 'hg':
408 from rhodecode.lib.vcs.backends.hg.repository import MercurialRepository
408 from rhodecode.lib.vcs.backends.hg.repository import MercurialRepository
409 from mercurial.httppeer import httppeer
409 from mercurial.httppeer import httppeer
410 if url.startswith('http'):
410 if url.startswith('http'):
411 ## initially check if it's at least the proper URL
411 ## initially check if it's at least the proper URL
412 ## or does it pass basic auth
412 ## or does it pass basic auth
413 MercurialRepository._check_url(url)
413 MercurialRepository._check_url(url)
414 httppeer(ui, url)._capabilities()
414 httppeer(ui, url)._capabilities()
415 elif url.startswith('svn+http'):
415 elif url.startswith('svn+http'):
416 from hgsubversion.svnrepo import svnremoterepo
416 from hgsubversion.svnrepo import svnremoterepo
417 svnremoterepo(ui, url).capabilities
417 svnremoterepo(ui, url).capabilities
418 elif url.startswith('git+http'):
418 elif url.startswith('git+http'):
419 raise NotImplementedError()
419 raise NotImplementedError()
420 else:
420 else:
421 raise Exception('clone from URI %s not allowed' % (url))
421 raise Exception('clone from URI %s not allowed' % (url))
422
422
423 elif repo_type == 'git':
423 elif repo_type == 'git':
424 from rhodecode.lib.vcs.backends.git.repository import GitRepository
424 from rhodecode.lib.vcs.backends.git.repository import GitRepository
425 if url.startswith('http'):
425 if url.startswith('http'):
426 ## initially check if it's at least the proper URL
426 ## initially check if it's at least the proper URL
427 ## or does it pass basic auth
427 ## or does it pass basic auth
428 GitRepository._check_url(url)
428 GitRepository._check_url(url)
429 elif url.startswith('svn+http'):
429 elif url.startswith('svn+http'):
430 raise NotImplementedError()
430 raise NotImplementedError()
431 elif url.startswith('hg+http'):
431 elif url.startswith('hg+http'):
432 raise NotImplementedError()
432 raise NotImplementedError()
433 else:
433 else:
434 raise Exception('clone from URI %s not allowed' % (url))
434 raise Exception('clone from URI %s not allowed' % (url))
435
435
436 class _validator(formencode.validators.FancyValidator):
436 class _validator(formencode.validators.FancyValidator):
437 messages = {
437 messages = {
438 'clone_uri': _(u'invalid clone url'),
438 'clone_uri': _(u'invalid clone url'),
439 'invalid_clone_uri': _(u'Invalid clone url, provide a '
439 'invalid_clone_uri': _(u'Invalid clone url, provide a '
440 'valid clone http(s)/svn+http(s) url')
440 'valid clone http(s)/svn+http(s) url')
441 }
441 }
442
442
443 def validate_python(self, value, state):
443 def validate_python(self, value, state):
444 repo_type = value.get('repo_type')
444 repo_type = value.get('repo_type')
445 url = value.get('clone_uri')
445 url = value.get('clone_uri')
446
446
447 if not url:
447 if not url:
448 pass
448 pass
449 else:
449 else:
450 try:
450 try:
451 url_handler(repo_type, url, make_ui('db', clear_session=False))
451 url_handler(repo_type, url, make_ui('db', clear_session=False))
452 except Exception:
452 except Exception:
453 log.exception('Url validation failed')
453 log.exception('Url validation failed')
454 msg = M(self, 'clone_uri')
454 msg = M(self, 'clone_uri')
455 raise formencode.Invalid(msg, value, state,
455 raise formencode.Invalid(msg, value, state,
456 error_dict=dict(clone_uri=msg)
456 error_dict=dict(clone_uri=msg)
457 )
457 )
458 return _validator
458 return _validator
459
459
460
460
461 def ValidForkType(old_data={}):
461 def ValidForkType(old_data={}):
462 class _validator(formencode.validators.FancyValidator):
462 class _validator(formencode.validators.FancyValidator):
463 messages = {
463 messages = {
464 'invalid_fork_type': _(u'Fork have to be the same type as parent')
464 'invalid_fork_type': _(u'Fork have to be the same type as parent')
465 }
465 }
466
466
467 def validate_python(self, value, state):
467 def validate_python(self, value, state):
468 if old_data['repo_type'] != value:
468 if old_data['repo_type'] != value:
469 msg = M(self, 'invalid_fork_type', state)
469 msg = M(self, 'invalid_fork_type', state)
470 raise formencode.Invalid(msg, value, state,
470 raise formencode.Invalid(msg, value, state,
471 error_dict=dict(repo_type=msg)
471 error_dict=dict(repo_type=msg)
472 )
472 )
473 return _validator
473 return _validator
474
474
475
475
476 def CanWriteGroup(old_data=None):
476 def CanWriteGroup(old_data=None):
477 class _validator(formencode.validators.FancyValidator):
477 class _validator(formencode.validators.FancyValidator):
478 messages = {
478 messages = {
479 'permission_denied': _(u"You don't have permissions "
479 'permission_denied': _(u"You don't have permissions "
480 "to create repository in this group"),
480 "to create repository in this group"),
481 'permission_denied_root': _(u"no permission to create repository "
481 'permission_denied_root': _(u"no permission to create repository "
482 "in root location")
482 "in root location")
483 }
483 }
484
484
485 def _to_python(self, value, state):
485 def _to_python(self, value, state):
486 #root location
486 #root location
487 if value in [-1, "-1"]:
487 if value in [-1, "-1"]:
488 return None
488 return None
489 return value
489 return value
490
490
491 def validate_python(self, value, state):
491 def validate_python(self, value, state):
492 gr = RepoGroup.get(value)
492 gr = RepoGroup.get(value)
493 gr_name = gr.group_name if gr else None # None means ROOT location
493 gr_name = gr.group_name if gr else None # None means ROOT location
494 val = HasReposGroupPermissionAny('group.write', 'group.admin')
494 val = HasReposGroupPermissionAny('group.write', 'group.admin')
495 can_create_repos = HasPermissionAny('hg.admin', 'hg.create.repository')
495 can_create_repos = HasPermissionAny('hg.admin', 'hg.create.repository')
496 forbidden = not val(gr_name, 'can write into group validator')
496 forbidden = not val(gr_name, 'can write into group validator')
497 value_changed = True # old_data['repo_group'].get('group_id') != safe_int(value)
497 value_changed = True # old_data['repo_group'].get('group_id') != safe_int(value)
498 if value_changed: # do check if we changed the value
498 if value_changed: # do check if we changed the value
499 #parent group need to be existing
499 #parent group need to be existing
500 if gr and forbidden:
500 if gr and forbidden:
501 msg = M(self, 'permission_denied', state)
501 msg = M(self, 'permission_denied', state)
502 raise formencode.Invalid(msg, value, state,
502 raise formencode.Invalid(msg, value, state,
503 error_dict=dict(repo_type=msg)
503 error_dict=dict(repo_type=msg)
504 )
504 )
505 ## check if we can write to root location !
505 ## check if we can write to root location !
506 elif gr is None and not can_create_repos():
506 elif gr is None and not can_create_repos():
507 msg = M(self, 'permission_denied_root', state)
507 msg = M(self, 'permission_denied_root', state)
508 raise formencode.Invalid(msg, value, state,
508 raise formencode.Invalid(msg, value, state,
509 error_dict=dict(repo_type=msg)
509 error_dict=dict(repo_type=msg)
510 )
510 )
511
511
512 return _validator
512 return _validator
513
513
514
514
515 def CanCreateGroup(can_create_in_root=False):
515 def CanCreateGroup(can_create_in_root=False):
516 class _validator(formencode.validators.FancyValidator):
516 class _validator(formencode.validators.FancyValidator):
517 messages = {
517 messages = {
518 'permission_denied': _(u"You don't have permissions "
518 'permission_denied': _(u"You don't have permissions "
519 "to create a group in this location")
519 "to create a group in this location")
520 }
520 }
521
521
522 def to_python(self, value, state):
522 def to_python(self, value, state):
523 #root location
523 #root location
524 if value in [-1, "-1"]:
524 if value in [-1, "-1"]:
525 return None
525 return None
526 return value
526 return value
527
527
528 def validate_python(self, value, state):
528 def validate_python(self, value, state):
529 gr = RepoGroup.get(value)
529 gr = RepoGroup.get(value)
530 gr_name = gr.group_name if gr else None # None means ROOT location
530 gr_name = gr.group_name if gr else None # None means ROOT location
531
531
532 if can_create_in_root and gr is None:
532 if can_create_in_root and gr is None:
533 #we can create in root, we're fine no validations required
533 #we can create in root, we're fine no validations required
534 return
534 return
535
535
536 forbidden_in_root = gr is None and not can_create_in_root
536 forbidden_in_root = gr is None and not can_create_in_root
537 val = HasReposGroupPermissionAny('group.admin')
537 val = HasReposGroupPermissionAny('group.admin')
538 forbidden = not val(gr_name, 'can create group validator')
538 forbidden = not val(gr_name, 'can create group validator')
539 if forbidden_in_root or forbidden:
539 if forbidden_in_root or forbidden:
540 msg = M(self, 'permission_denied', state)
540 msg = M(self, 'permission_denied', state)
541 raise formencode.Invalid(msg, value, state,
541 raise formencode.Invalid(msg, value, state,
542 error_dict=dict(group_parent_id=msg)
542 error_dict=dict(group_parent_id=msg)
543 )
543 )
544
544
545 return _validator
545 return _validator
546
546
547
547
548 def ValidPerms(type_='repo'):
548 def ValidPerms(type_='repo'):
549 if type_ == 'group':
549 if type_ == 'group':
550 EMPTY_PERM = 'group.none'
550 EMPTY_PERM = 'group.none'
551 elif type_ == 'repo':
551 elif type_ == 'repo':
552 EMPTY_PERM = 'repository.none'
552 EMPTY_PERM = 'repository.none'
553
553
554 class _validator(formencode.validators.FancyValidator):
554 class _validator(formencode.validators.FancyValidator):
555 messages = {
555 messages = {
556 'perm_new_member_name':
556 'perm_new_member_name':
557 _(u'This username or user group name is not valid')
557 _(u'This username or user group name is not valid')
558 }
558 }
559
559
560 def to_python(self, value, state):
560 def to_python(self, value, state):
561 perms_update = OrderedSet()
561 perms_update = OrderedSet()
562 perms_new = OrderedSet()
562 perms_new = OrderedSet()
563 # build a list of permission to update and new permission to create
563 # build a list of permission to update and new permission to create
564
564
565 #CLEAN OUT ORG VALUE FROM NEW MEMBERS, and group them using
565 #CLEAN OUT ORG VALUE FROM NEW MEMBERS, and group them using
566 new_perms_group = defaultdict(dict)
566 new_perms_group = defaultdict(dict)
567 for k, v in value.copy().iteritems():
567 for k, v in value.copy().iteritems():
568 if k.startswith('perm_new_member'):
568 if k.startswith('perm_new_member'):
569 del value[k]
569 del value[k]
570 _type, part = k.split('perm_new_member_')
570 _type, part = k.split('perm_new_member_')
571 args = part.split('_')
571 args = part.split('_')
572 if len(args) == 1:
572 if len(args) == 1:
573 new_perms_group[args[0]]['perm'] = v
573 new_perms_group[args[0]]['perm'] = v
574 elif len(args) == 2:
574 elif len(args) == 2:
575 _key, pos = args
575 _key, pos = args
576 new_perms_group[pos][_key] = v
576 new_perms_group[pos][_key] = v
577
577
578 # fill new permissions in order of how they were added
578 # fill new permissions in order of how they were added
579 for k in sorted(map(int, new_perms_group.keys())):
579 for k in sorted(map(int, new_perms_group.keys())):
580 perm_dict = new_perms_group[str(k)]
580 perm_dict = new_perms_group[str(k)]
581 new_member = perm_dict.get('name')
581 new_member = perm_dict.get('name')
582 new_perm = perm_dict.get('perm')
582 new_perm = perm_dict.get('perm')
583 new_type = perm_dict.get('type')
583 new_type = perm_dict.get('type')
584 if new_member and new_perm and new_type:
584 if new_member and new_perm and new_type:
585 perms_new.add((new_member, new_perm, new_type))
585 perms_new.add((new_member, new_perm, new_type))
586
586
587 for k, v in value.iteritems():
587 for k, v in value.iteritems():
588 if k.startswith('u_perm_') or k.startswith('g_perm_'):
588 if k.startswith('u_perm_') or k.startswith('g_perm_'):
589 member = k[7:]
589 member = k[7:]
590 t = {'u': 'user',
590 t = {'u': 'user',
591 'g': 'users_group'
591 'g': 'users_group'
592 }[k[0]]
592 }[k[0]]
593 if member == 'default':
593 if member == 'default':
594 if str2bool(value.get('repo_private')):
594 if str2bool(value.get('repo_private')):
595 # set none for default when updating to
595 # set none for default when updating to
596 # private repo protects agains form manipulation
596 # private repo protects agains form manipulation
597 v = EMPTY_PERM
597 v = EMPTY_PERM
598 perms_update.add((member, v, t))
598 perms_update.add((member, v, t))
599
599
600 value['perms_updates'] = list(perms_update)
600 value['perms_updates'] = list(perms_update)
601 value['perms_new'] = list(perms_new)
601 value['perms_new'] = list(perms_new)
602
602
603 # update permissions
603 # update permissions
604 for k, v, t in perms_new:
604 for k, v, t in perms_new:
605 try:
605 try:
606 if t is 'user':
606 if t is 'user':
607 self.user_db = User.query()\
607 self.user_db = User.query()\
608 .filter(User.active == True)\
608 .filter(User.active == True)\
609 .filter(User.username == k).one()
609 .filter(User.username == k).one()
610 if t is 'users_group':
610 if t is 'users_group':
611 self.user_db = UserGroup.query()\
611 self.user_db = UserGroup.query()\
612 .filter(UserGroup.users_group_active == True)\
612 .filter(UserGroup.users_group_active == True)\
613 .filter(UserGroup.users_group_name == k).one()
613 .filter(UserGroup.users_group_name == k).one()
614
614
615 except Exception:
615 except Exception:
616 log.exception('Updated permission failed')
616 log.exception('Updated permission failed')
617 msg = M(self, 'perm_new_member_type', state)
617 msg = M(self, 'perm_new_member_type', state)
618 raise formencode.Invalid(msg, value, state,
618 raise formencode.Invalid(msg, value, state,
619 error_dict=dict(perm_new_member_name=msg)
619 error_dict=dict(perm_new_member_name=msg)
620 )
620 )
621 return value
621 return value
622 return _validator
622 return _validator
623
623
624
624
625 def ValidSettings():
625 def ValidSettings():
626 class _validator(formencode.validators.FancyValidator):
626 class _validator(formencode.validators.FancyValidator):
627 def _to_python(self, value, state):
627 def _to_python(self, value, state):
628 # settings form for users that are not admin
628 # settings form for users that are not admin
629 # can't edit certain parameters, it's extra backup if they mangle
629 # can't edit certain parameters, it's extra backup if they mangle
630 # with forms
630 # with forms
631
631
632 forbidden_params = [
632 forbidden_params = [
633 'user', 'repo_type', 'repo_enable_locking',
633 'user', 'repo_type', 'repo_enable_locking',
634 'repo_enable_downloads', 'repo_enable_statistics'
634 'repo_enable_downloads', 'repo_enable_statistics'
635 ]
635 ]
636
636
637 for param in forbidden_params:
637 for param in forbidden_params:
638 if param in value:
638 if param in value:
639 del value[param]
639 del value[param]
640 return value
640 return value
641
641
642 def validate_python(self, value, state):
642 def validate_python(self, value, state):
643 pass
643 pass
644 return _validator
644 return _validator
645
645
646
646
647 def ValidPath():
647 def ValidPath():
648 class _validator(formencode.validators.FancyValidator):
648 class _validator(formencode.validators.FancyValidator):
649 messages = {
649 messages = {
650 'invalid_path': _(u'This is not a valid path')
650 'invalid_path': _(u'This is not a valid path')
651 }
651 }
652
652
653 def validate_python(self, value, state):
653 def validate_python(self, value, state):
654 if not os.path.isdir(value):
654 if not os.path.isdir(value):
655 msg = M(self, 'invalid_path', state)
655 msg = M(self, 'invalid_path', state)
656 raise formencode.Invalid(msg, value, state,
656 raise formencode.Invalid(msg, value, state,
657 error_dict=dict(paths_root_path=msg)
657 error_dict=dict(paths_root_path=msg)
658 )
658 )
659 return _validator
659 return _validator
660
660
661
661
662 def UniqSystemEmail(old_data={}):
662 def UniqSystemEmail(old_data={}):
663 class _validator(formencode.validators.FancyValidator):
663 class _validator(formencode.validators.FancyValidator):
664 messages = {
664 messages = {
665 'email_taken': _(u'This e-mail address is already taken')
665 'email_taken': _(u'This e-mail address is already taken')
666 }
666 }
667
667
668 def _to_python(self, value, state):
668 def _to_python(self, value, state):
669 return value.lower()
669 return value.lower()
670
670
671 def validate_python(self, value, state):
671 def validate_python(self, value, state):
672 if (old_data.get('email') or '').lower() != value:
672 if (old_data.get('email') or '').lower() != value:
673 user = User.get_by_email(value, case_insensitive=True)
673 user = User.get_by_email(value, case_insensitive=True)
674 if user:
674 if user:
675 msg = M(self, 'email_taken', state)
675 msg = M(self, 'email_taken', state)
676 raise formencode.Invalid(msg, value, state,
676 raise formencode.Invalid(msg, value, state,
677 error_dict=dict(email=msg)
677 error_dict=dict(email=msg)
678 )
678 )
679 return _validator
679 return _validator
680
680
681
681
682 def ValidSystemEmail():
682 def ValidSystemEmail():
683 class _validator(formencode.validators.FancyValidator):
683 class _validator(formencode.validators.FancyValidator):
684 messages = {
684 messages = {
685 'non_existing_email': _(u'e-mail "%(email)s" does not exist.')
685 'non_existing_email': _(u'e-mail "%(email)s" does not exist.')
686 }
686 }
687
687
688 def _to_python(self, value, state):
688 def _to_python(self, value, state):
689 return value.lower()
689 return value.lower()
690
690
691 def validate_python(self, value, state):
691 def validate_python(self, value, state):
692 user = User.get_by_email(value, case_insensitive=True)
692 user = User.get_by_email(value, case_insensitive=True)
693 if user is None:
693 if user is None:
694 msg = M(self, 'non_existing_email', state, email=value)
694 msg = M(self, 'non_existing_email', state, email=value)
695 raise formencode.Invalid(msg, value, state,
695 raise formencode.Invalid(msg, value, state,
696 error_dict=dict(email=msg)
696 error_dict=dict(email=msg)
697 )
697 )
698
698
699 return _validator
699 return _validator
700
700
701
701
702 def LdapLibValidator():
702 def LdapLibValidator():
703 class _validator(formencode.validators.FancyValidator):
703 class _validator(formencode.validators.FancyValidator):
704 messages = {
704 messages = {
705
705
706 }
706 }
707
707
708 def validate_python(self, value, state):
708 def validate_python(self, value, state):
709 try:
709 try:
710 import ldap
710 import ldap
711 ldap # pyflakes silence !
711 ldap # pyflakes silence !
712 except ImportError:
712 except ImportError:
713 raise LdapImportError()
713 raise LdapImportError()
714
714
715 return _validator
715 return _validator
716
716
717
717
718 def AttrLoginValidator():
718 def AttrLoginValidator():
719 class _validator(formencode.validators.FancyValidator):
719 class _validator(formencode.validators.FancyValidator):
720 messages = {
720 messages = {
721 'invalid_cn':
721 'invalid_cn':
722 _(u'The LDAP Login attribute of the CN must be specified - '
722 _(u'The LDAP Login attribute of the CN must be specified - '
723 'this is the name of the attribute that is equivalent '
723 'this is the name of the attribute that is equivalent '
724 'to "username"')
724 'to "username"')
725 }
725 }
726
726 messages['empty'] = messages['invalid_cn']
727 def validate_python(self, value, state):
728 if not value or not isinstance(value, (str, unicode)):
729 msg = M(self, 'invalid_cn', state)
730 raise formencode.Invalid(msg, value, state,
731 error_dict=dict(ldap_attr_login=msg)
732 )
733
727
734 return _validator
728 return _validator
735
729
736
730
737 def NotReviewedRevisions(repo_id):
731 def NotReviewedRevisions(repo_id):
738 class _validator(formencode.validators.FancyValidator):
732 class _validator(formencode.validators.FancyValidator):
739 messages = {
733 messages = {
740 'rev_already_reviewed':
734 'rev_already_reviewed':
741 _(u'Revisions %(revs)s are already part of pull request '
735 _(u'Revisions %(revs)s are already part of pull request '
742 'or have set status')
736 'or have set status')
743 }
737 }
744
738
745 def validate_python(self, value, state):
739 def validate_python(self, value, state):
746 # check revisions if they are not reviewed, or a part of another
740 # check revisions if they are not reviewed, or a part of another
747 # pull request
741 # pull request
748 statuses = ChangesetStatus.query()\
742 statuses = ChangesetStatus.query()\
749 .filter(ChangesetStatus.revision.in_(value))\
743 .filter(ChangesetStatus.revision.in_(value))\
750 .filter(ChangesetStatus.repo_id == repo_id)\
744 .filter(ChangesetStatus.repo_id == repo_id)\
751 .all()
745 .all()
752
746
753 errors = []
747 errors = []
754 for cs in statuses:
748 for cs in statuses:
755 if cs.pull_request_id:
749 if cs.pull_request_id:
756 errors.append(['pull_req', cs.revision[:12]])
750 errors.append(['pull_req', cs.revision[:12]])
757 elif cs.status:
751 elif cs.status:
758 errors.append(['status', cs.revision[:12]])
752 errors.append(['status', cs.revision[:12]])
759
753
760 if errors:
754 if errors:
761 revs = ','.join([x[1] for x in errors])
755 revs = ','.join([x[1] for x in errors])
762 msg = M(self, 'rev_already_reviewed', state, revs=revs)
756 msg = M(self, 'rev_already_reviewed', state, revs=revs)
763 raise formencode.Invalid(msg, value, state,
757 raise formencode.Invalid(msg, value, state,
764 error_dict=dict(revisions=revs)
758 error_dict=dict(revisions=revs)
765 )
759 )
766
760
767 return _validator
761 return _validator
768
762
769
763
770 def ValidIp():
764 def ValidIp():
771 class _validator(CIDR):
765 class _validator(CIDR):
772 messages = dict(
766 messages = dict(
773 badFormat=_('Please enter a valid IPv4 or IpV6 address'),
767 badFormat=_('Please enter a valid IPv4 or IpV6 address'),
774 illegalBits=_('The network size (bits) must be within the range'
768 illegalBits=_('The network size (bits) must be within the range'
775 ' of 0-32 (not %(bits)r)'))
769 ' of 0-32 (not %(bits)r)'))
776
770
777 def to_python(self, value, state):
771 def to_python(self, value, state):
778 v = super(_validator, self).to_python(value, state)
772 v = super(_validator, self).to_python(value, state)
779 v = v.strip()
773 v = v.strip()
780 net = ipaddr.IPNetwork(address=v)
774 net = ipaddr.IPNetwork(address=v)
781 if isinstance(net, ipaddr.IPv4Network):
775 if isinstance(net, ipaddr.IPv4Network):
782 #if IPv4 doesn't end with a mask, add /32
776 #if IPv4 doesn't end with a mask, add /32
783 if '/' not in value:
777 if '/' not in value:
784 v += '/32'
778 v += '/32'
785 if isinstance(net, ipaddr.IPv6Network):
779 if isinstance(net, ipaddr.IPv6Network):
786 #if IPv6 doesn't end with a mask, add /128
780 #if IPv6 doesn't end with a mask, add /128
787 if '/' not in value:
781 if '/' not in value:
788 v += '/128'
782 v += '/128'
789 return v
783 return v
790
784
791 def validate_python(self, value, state):
785 def validate_python(self, value, state):
792 try:
786 try:
793 addr = value.strip()
787 addr = value.strip()
794 #this raises an ValueError if address is not IpV4 or IpV6
788 #this raises an ValueError if address is not IpV4 or IpV6
795 ipaddr.IPNetwork(address=addr)
789 ipaddr.IPNetwork(address=addr)
796 except ValueError:
790 except ValueError:
797 raise formencode.Invalid(self.message('badFormat', state),
791 raise formencode.Invalid(self.message('badFormat', state),
798 value, state)
792 value, state)
799
793
800 return _validator
794 return _validator
801
795
802
796
803 def FieldKey():
797 def FieldKey():
804 class _validator(formencode.validators.FancyValidator):
798 class _validator(formencode.validators.FancyValidator):
805 messages = dict(
799 messages = dict(
806 badFormat=_('Key name can only consist of letters, '
800 badFormat=_('Key name can only consist of letters, '
807 'underscore, dash or numbers'),)
801 'underscore, dash or numbers'),)
808
802
809 def validate_python(self, value, state):
803 def validate_python(self, value, state):
810 if not re.match('[a-zA-Z0-9_-]+$', value):
804 if not re.match('[a-zA-Z0-9_-]+$', value):
811 raise formencode.Invalid(self.message('badFormat', state),
805 raise formencode.Invalid(self.message('badFormat', state),
812 value, state)
806 value, state)
813 return _validator
807 return _validator
@@ -1,175 +1,184 b''
1 """Pylons application test package
1 """Pylons application test package
2
2
3 This package assumes the Pylons environment is already loaded, such as
3 This package assumes the Pylons environment is already loaded, such as
4 when this script is imported from the `nosetests --with-pylons=test.ini`
4 when this script is imported from the `nosetests --with-pylons=test.ini`
5 command.
5 command.
6
6
7 This module initializes the application via ``websetup`` (`paster
7 This module initializes the application via ``websetup`` (`paster
8 setup-app`) and provides the base testing objects.
8 setup-app`) and provides the base testing objects.
9
9
10 nosetests -x - fail on first error
10 nosetests -x - fail on first error
11 nosetests rhodecode.tests.functional.test_admin_settings:TestSettingsController.test_my_account
11 nosetests rhodecode.tests.functional.test_admin_settings:TestSettingsController.test_my_account
12 nosetests --pdb --pdb-failures
12 nosetests --pdb --pdb-failures
13 nosetests --with-coverage --cover-package=rhodecode.model.validators rhodecode.tests.test_validators
13 nosetests --with-coverage --cover-package=rhodecode.model.validators rhodecode.tests.test_validators
14
14
15 optional FLAGS:
15 optional FLAGS:
16 RC_WHOOSH_TEST_DISABLE=1 - skip whoosh index building and tests
16 RC_WHOOSH_TEST_DISABLE=1 - skip whoosh index building and tests
17 RC_NO_TMP_PATH=1 - disable new temp path for tests, used mostly for test_vcs_operations
17 RC_NO_TMP_PATH=1 - disable new temp path for tests, used mostly for test_vcs_operations
18
18
19 """
19 """
20 import os
20 import os
21 import time
21 import time
22 import logging
22 import logging
23 import datetime
23 import datetime
24 import hashlib
24 import hashlib
25 import tempfile
25 import tempfile
26 from os.path import join as jn
26 from os.path import join as jn
27
27
28 from unittest import TestCase
28 from unittest import TestCase
29 from tempfile import _RandomNameSequence
29 from tempfile import _RandomNameSequence
30
30
31 from paste.deploy import loadapp
31 from paste.deploy import loadapp
32 from paste.script.appinstall import SetupCommand
32 from paste.script.appinstall import SetupCommand
33 from pylons import config, url
33 from pylons import config, url
34 from routes.util import URLGenerator
34 from routes.util import URLGenerator
35 from webtest import TestApp
35 from webtest import TestApp
36 from nose.plugins.skip import SkipTest
36 from nose.plugins.skip import SkipTest
37
37
38 from rhodecode import is_windows
38 from rhodecode import is_windows
39 from rhodecode.model.meta import Session
39 from rhodecode.model.meta import Session
40 from rhodecode.model.db import User
40 from rhodecode.model.db import User
41 from rhodecode.tests.nose_parametrized import parameterized
41 from rhodecode.tests.nose_parametrized import parameterized
42
42
43 import pylons.test
43 import pylons.test
44 from rhodecode.lib.utils2 import safe_unicode, safe_str
44 from rhodecode.lib.utils2 import safe_unicode, safe_str
45
45
46
46
47 os.environ['TZ'] = 'UTC'
47 os.environ['TZ'] = 'UTC'
48 if not is_windows:
48 if not is_windows:
49 time.tzset()
49 time.tzset()
50
50
51 log = logging.getLogger(__name__)
51 log = logging.getLogger(__name__)
52
52
53 __all__ = [
53 __all__ = [
54 'parameterized', 'environ', 'url', 'get_new_dir', 'TestController',
54 'parameterized', 'environ', 'url', 'get_new_dir', 'TestController',
55 'SkipTest',
55 'SkipTest', 'ldap_lib_installed',
56 'TESTS_TMP_PATH', 'HG_REPO', 'GIT_REPO', 'NEW_HG_REPO', 'NEW_GIT_REPO',
56 'TESTS_TMP_PATH', 'HG_REPO', 'GIT_REPO', 'NEW_HG_REPO', 'NEW_GIT_REPO',
57 'HG_FORK', 'GIT_FORK', 'TEST_USER_ADMIN_LOGIN', 'TEST_USER_ADMIN_PASS',
57 'HG_FORK', 'GIT_FORK', 'TEST_USER_ADMIN_LOGIN', 'TEST_USER_ADMIN_PASS',
58 'TEST_USER_REGULAR_LOGIN', 'TEST_USER_REGULAR_PASS',
58 'TEST_USER_REGULAR_LOGIN', 'TEST_USER_REGULAR_PASS',
59 'TEST_USER_REGULAR_EMAIL', 'TEST_USER_REGULAR2_LOGIN',
59 'TEST_USER_REGULAR_EMAIL', 'TEST_USER_REGULAR2_LOGIN',
60 'TEST_USER_REGULAR2_PASS', 'TEST_USER_REGULAR2_EMAIL', 'TEST_HG_REPO',
60 'TEST_USER_REGULAR2_PASS', 'TEST_USER_REGULAR2_EMAIL', 'TEST_HG_REPO',
61 'TEST_HG_REPO_CLONE', 'TEST_HG_REPO_PULL', 'TEST_GIT_REPO',
61 'TEST_HG_REPO_CLONE', 'TEST_HG_REPO_PULL', 'TEST_GIT_REPO',
62 'TEST_GIT_REPO_CLONE', 'TEST_GIT_REPO_PULL', 'HG_REMOTE_REPO',
62 'TEST_GIT_REPO_CLONE', 'TEST_GIT_REPO_PULL', 'HG_REMOTE_REPO',
63 'GIT_REMOTE_REPO', 'SCM_TESTS',
63 'GIT_REMOTE_REPO', 'SCM_TESTS',
64 ]
64 ]
65
65
66 # Invoke websetup with the current config file
66 # Invoke websetup with the current config file
67 # SetupCommand('setup-app').run([config_file])
67 # SetupCommand('setup-app').run([config_file])
68
68
69 environ = {}
69 environ = {}
70
70
71 #SOME GLOBALS FOR TESTS
71 #SOME GLOBALS FOR TESTS
72
72
73 TESTS_TMP_PATH = jn('/', 'tmp', 'rc_test_%s' % _RandomNameSequence().next())
73 TESTS_TMP_PATH = jn('/', 'tmp', 'rc_test_%s' % _RandomNameSequence().next())
74 TEST_USER_ADMIN_LOGIN = 'test_admin'
74 TEST_USER_ADMIN_LOGIN = 'test_admin'
75 TEST_USER_ADMIN_PASS = 'test12'
75 TEST_USER_ADMIN_PASS = 'test12'
76 TEST_USER_ADMIN_EMAIL = 'test_admin@mail.com'
76 TEST_USER_ADMIN_EMAIL = 'test_admin@mail.com'
77
77
78 TEST_USER_REGULAR_LOGIN = 'test_regular'
78 TEST_USER_REGULAR_LOGIN = 'test_regular'
79 TEST_USER_REGULAR_PASS = 'test12'
79 TEST_USER_REGULAR_PASS = 'test12'
80 TEST_USER_REGULAR_EMAIL = 'test_regular@mail.com'
80 TEST_USER_REGULAR_EMAIL = 'test_regular@mail.com'
81
81
82 TEST_USER_REGULAR2_LOGIN = 'test_regular2'
82 TEST_USER_REGULAR2_LOGIN = 'test_regular2'
83 TEST_USER_REGULAR2_PASS = 'test12'
83 TEST_USER_REGULAR2_PASS = 'test12'
84 TEST_USER_REGULAR2_EMAIL = 'test_regular2@mail.com'
84 TEST_USER_REGULAR2_EMAIL = 'test_regular2@mail.com'
85
85
86 HG_REPO = 'vcs_test_hg'
86 HG_REPO = 'vcs_test_hg'
87 GIT_REPO = 'vcs_test_git'
87 GIT_REPO = 'vcs_test_git'
88
88
89 NEW_HG_REPO = 'vcs_test_hg_new'
89 NEW_HG_REPO = 'vcs_test_hg_new'
90 NEW_GIT_REPO = 'vcs_test_git_new'
90 NEW_GIT_REPO = 'vcs_test_git_new'
91
91
92 HG_FORK = 'vcs_test_hg_fork'
92 HG_FORK = 'vcs_test_hg_fork'
93 GIT_FORK = 'vcs_test_git_fork'
93 GIT_FORK = 'vcs_test_git_fork'
94
94
95 ## VCS
95 ## VCS
96 SCM_TESTS = ['hg', 'git']
96 SCM_TESTS = ['hg', 'git']
97 uniq_suffix = str(int(time.mktime(datetime.datetime.now().timetuple())))
97 uniq_suffix = str(int(time.mktime(datetime.datetime.now().timetuple())))
98
98
99 GIT_REMOTE_REPO = 'git://github.com/codeinn/vcs.git'
99 GIT_REMOTE_REPO = 'git://github.com/codeinn/vcs.git'
100
100
101 TEST_GIT_REPO = jn(TESTS_TMP_PATH, GIT_REPO)
101 TEST_GIT_REPO = jn(TESTS_TMP_PATH, GIT_REPO)
102 TEST_GIT_REPO_CLONE = jn(TESTS_TMP_PATH, 'vcsgitclone%s' % uniq_suffix)
102 TEST_GIT_REPO_CLONE = jn(TESTS_TMP_PATH, 'vcsgitclone%s' % uniq_suffix)
103 TEST_GIT_REPO_PULL = jn(TESTS_TMP_PATH, 'vcsgitpull%s' % uniq_suffix)
103 TEST_GIT_REPO_PULL = jn(TESTS_TMP_PATH, 'vcsgitpull%s' % uniq_suffix)
104
104
105
105
106 HG_REMOTE_REPO = 'http://bitbucket.org/marcinkuzminski/vcs'
106 HG_REMOTE_REPO = 'http://bitbucket.org/marcinkuzminski/vcs'
107
107
108 TEST_HG_REPO = jn(TESTS_TMP_PATH, HG_REPO)
108 TEST_HG_REPO = jn(TESTS_TMP_PATH, HG_REPO)
109 TEST_HG_REPO_CLONE = jn(TESTS_TMP_PATH, 'vcshgclone%s' % uniq_suffix)
109 TEST_HG_REPO_CLONE = jn(TESTS_TMP_PATH, 'vcshgclone%s' % uniq_suffix)
110 TEST_HG_REPO_PULL = jn(TESTS_TMP_PATH, 'vcshgpull%s' % uniq_suffix)
110 TEST_HG_REPO_PULL = jn(TESTS_TMP_PATH, 'vcshgpull%s' % uniq_suffix)
111
111
112 TEST_DIR = tempfile.gettempdir()
112 TEST_DIR = tempfile.gettempdir()
113 TEST_REPO_PREFIX = 'vcs-test'
113 TEST_REPO_PREFIX = 'vcs-test'
114
114
115 # cached repos if any !
115 # cached repos if any !
116 # comment out to get some other repos from bb or github
116 # comment out to get some other repos from bb or github
117 GIT_REMOTE_REPO = jn(TESTS_TMP_PATH, GIT_REPO)
117 GIT_REMOTE_REPO = jn(TESTS_TMP_PATH, GIT_REPO)
118 HG_REMOTE_REPO = jn(TESTS_TMP_PATH, HG_REPO)
118 HG_REMOTE_REPO = jn(TESTS_TMP_PATH, HG_REPO)
119
119
120 #skip ldap tests if LDAP lib is not installed
121 ldap_lib_installed = False
122 try:
123 import ldap
124 ldap_lib_installed = True
125 except ImportError:
126 # means that python-ldap is not installed
127 pass
128
120
129
121 def get_new_dir(title):
130 def get_new_dir(title):
122 """
131 """
123 Returns always new directory path.
132 Returns always new directory path.
124 """
133 """
125 from rhodecode.tests.vcs.utils import get_normalized_path
134 from rhodecode.tests.vcs.utils import get_normalized_path
126 name = TEST_REPO_PREFIX
135 name = TEST_REPO_PREFIX
127 if title:
136 if title:
128 name = '-'.join((name, title))
137 name = '-'.join((name, title))
129 hex = hashlib.sha1(str(time.time())).hexdigest()
138 hex = hashlib.sha1(str(time.time())).hexdigest()
130 name = '-'.join((name, hex))
139 name = '-'.join((name, hex))
131 path = os.path.join(TEST_DIR, name)
140 path = os.path.join(TEST_DIR, name)
132 return get_normalized_path(path)
141 return get_normalized_path(path)
133
142
134
143
135 class TestController(TestCase):
144 class TestController(TestCase):
136
145
137 def __init__(self, *args, **kwargs):
146 def __init__(self, *args, **kwargs):
138 wsgiapp = pylons.test.pylonsapp
147 wsgiapp = pylons.test.pylonsapp
139 config = wsgiapp.config
148 config = wsgiapp.config
140
149
141 self.app = TestApp(wsgiapp)
150 self.app = TestApp(wsgiapp)
142 url._push_object(URLGenerator(config['routes.map'], environ))
151 url._push_object(URLGenerator(config['routes.map'], environ))
143 self.Session = Session
152 self.Session = Session
144 self.index_location = config['app_conf']['index_dir']
153 self.index_location = config['app_conf']['index_dir']
145 TestCase.__init__(self, *args, **kwargs)
154 TestCase.__init__(self, *args, **kwargs)
146
155
147 def log_user(self, username=TEST_USER_ADMIN_LOGIN,
156 def log_user(self, username=TEST_USER_ADMIN_LOGIN,
148 password=TEST_USER_ADMIN_PASS):
157 password=TEST_USER_ADMIN_PASS):
149 self._logged_username = username
158 self._logged_username = username
150 response = self.app.post(url(controller='login', action='index'),
159 response = self.app.post(url(controller='login', action='index'),
151 {'username': username,
160 {'username': username,
152 'password': password})
161 'password': password})
153
162
154 if 'invalid user name' in response.body:
163 if 'invalid user name' in response.body:
155 self.fail('could not login using %s %s' % (username, password))
164 self.fail('could not login using %s %s' % (username, password))
156
165
157 self.assertEqual(response.status, '302 Found')
166 self.assertEqual(response.status, '302 Found')
158 ses = response.session['rhodecode_user']
167 ses = response.session['rhodecode_user']
159 self.assertEqual(ses.get('username'), username)
168 self.assertEqual(ses.get('username'), username)
160 response = response.follow()
169 response = response.follow()
161 self.assertEqual(ses.get('is_authenticated'), True)
170 self.assertEqual(ses.get('is_authenticated'), True)
162
171
163 return response.session['rhodecode_user']
172 return response.session['rhodecode_user']
164
173
165 def _get_logged_user(self):
174 def _get_logged_user(self):
166 return User.get_by_username(self._logged_username)
175 return User.get_by_username(self._logged_username)
167
176
168 def checkSessionFlash(self, response, msg):
177 def checkSessionFlash(self, response, msg):
169 self.assertTrue('flash' in response.session,
178 self.assertTrue('flash' in response.session,
170 msg='Response session:%r have no flash'
179 msg='Response session:%r have no flash'
171 % response.session)
180 % response.session)
172 if not msg in response.session['flash'][0][1]:
181 if not msg in response.session['flash'][0][1]:
173 msg = u'msg `%s` not found in session flash: got `%s` instead' % (
182 msg = u'msg `%s` not found in session flash: got `%s` instead' % (
174 msg, response.session['flash'][0][1])
183 msg, response.session['flash'][0][1])
175 self.fail(safe_str(msg))
184 self.fail(safe_str(msg))
@@ -1,85 +1,98 b''
1 from rhodecode.tests import *
1 from rhodecode.tests import *
2 from rhodecode.model.db import RhodeCodeSetting
2 from rhodecode.model.db import RhodeCodeSetting
3
3
4 skip_ldap_test = False
5 try:
6 import ldap
7 except ImportError:
8 # means that python-ldap is not installed
9 skip_ldap_test = True
10 pass
11
12
13 class TestLdapSettingsController(TestController):
4 class TestLdapSettingsController(TestController):
14
5
15 def test_index(self):
6 def test_index(self):
16 self.log_user()
7 self.log_user()
17 response = self.app.get(url(controller='admin/ldap_settings',
8 response = self.app.get(url(controller='admin/ldap_settings',
18 action='index'))
9 action='index'))
19 response.mustcontain('LDAP administration')
10 response.mustcontain('LDAP administration')
20
11
21 def test_ldap_save_settings(self):
12 def test_ldap_save_settings(self):
22 self.log_user()
13 self.log_user()
23 if skip_ldap_test:
14 if ldap_lib_installed:
24 raise SkipTest('skipping due to missing ldap lib')
15 raise SkipTest('skipping due to missing ldap lib')
25
16
26 test_url = url(controller='admin/ldap_settings',
17 test_url = url(controller='admin/ldap_settings',
27 action='ldap_settings')
18 action='ldap_settings')
28
19
29 response = self.app.post(url=test_url,
20 response = self.app.post(url=test_url,
30 params={'ldap_host' : u'dc.example.com',
21 params={'ldap_host': u'dc.example.com',
31 'ldap_port' : '999',
22 'ldap_port': '999',
32 'ldap_tls_kind' : 'PLAIN',
23 'ldap_tls_kind': 'PLAIN',
33 'ldap_tls_reqcert' : 'NEVER',
24 'ldap_tls_reqcert': 'NEVER',
34 'ldap_dn_user':'test_user',
25 'ldap_dn_user': 'test_user',
35 'ldap_dn_pass':'test_pass',
26 'ldap_dn_pass': 'test_pass',
36 'ldap_base_dn':'test_base_dn',
27 'ldap_base_dn': 'test_base_dn',
37 'ldap_filter':'test_filter',
28 'ldap_filter': 'test_filter',
38 'ldap_search_scope':'BASE',
29 'ldap_search_scope': 'BASE',
39 'ldap_attr_login':'test_attr_login',
30 'ldap_attr_login': 'test_attr_login',
40 'ldap_attr_firstname':'ima',
31 'ldap_attr_firstname': 'ima',
41 'ldap_attr_lastname':'tester',
32 'ldap_attr_lastname': 'tester',
42 'ldap_attr_email':'test@example.com' })
33 'ldap_attr_email': 'test@example.com' })
43
34
44 new_settings = RhodeCodeSetting.get_ldap_settings()
35 new_settings = RhodeCodeSetting.get_ldap_settings()
45 self.assertEqual(new_settings['ldap_host'], u'dc.example.com',
36 self.assertEqual(new_settings['ldap_host'], u'dc.example.com',
46 'fail db write compare')
37 'fail db write compare')
47
38
48 self.checkSessionFlash(response,
39 self.checkSessionFlash(response,
49 'LDAP settings updated successfully')
40 'LDAP settings updated successfully')
50
41
51 def test_ldap_error_form(self):
42 def test_ldap_error_form_wrong_port_number(self):
52 self.log_user()
43 self.log_user()
53 if skip_ldap_test:
44 if ldap_lib_installed:
54 raise SkipTest('skipping due to missing ldap lib')
45 raise SkipTest('skipping due to missing ldap lib')
55
46
56 test_url = url(controller='admin/ldap_settings',
47 test_url = url(controller='admin/ldap_settings',
57 action='ldap_settings')
48 action='ldap_settings')
58
49
59 response = self.app.post(url=test_url,
50 response = self.app.post(url=test_url,
60 params={'ldap_host' : '',
51 params={'ldap_host': '',
61 'ldap_port' : 'i-should-be-number',
52 'ldap_port': 'i-should-be-number', # bad port num
62 'ldap_tls_kind' : 'PLAIN',
53 'ldap_tls_kind': 'PLAIN',
63 'ldap_tls_reqcert' : 'NEVER',
54 'ldap_tls_reqcert': 'NEVER',
64 'ldap_dn_user':'',
55 'ldap_dn_user': '',
65 'ldap_dn_pass':'',
56 'ldap_dn_pass': '',
66 'ldap_base_dn':'',
57 'ldap_base_dn': '',
67 'ldap_filter':'',
58 'ldap_filter': '',
68 'ldap_search_scope':'BASE',
59 'ldap_search_scope': 'BASE',
69 'ldap_attr_login':'', # <----- missing required input
60 'ldap_attr_login': '',
70 'ldap_attr_firstname':'',
61 'ldap_attr_firstname': '',
71 'ldap_attr_lastname':'',
62 'ldap_attr_lastname': '',
72 'ldap_attr_email':'' })
63 'ldap_attr_email': ''})
64
65 response.mustcontain("""<span class="error-message">"""
66 """Please enter a number</span><br />""")
67
68 def test_ldap_error_form(self):
69 self.log_user()
70 if ldap_lib_installed:
71 raise SkipTest('skipping due to missing ldap lib')
72
73 test_url = url(controller='admin/ldap_settings',
74 action='ldap_settings')
75
76 response = self.app.post(url=test_url,
77 params={'ldap_host': 'Host',
78 'ldap_port': '123',
79 'ldap_tls_kind': 'PLAIN',
80 'ldap_tls_reqcert': 'NEVER',
81 'ldap_dn_user': '',
82 'ldap_dn_pass': '',
83 'ldap_base_dn': '',
84 'ldap_filter': '',
85 'ldap_search_scope': 'BASE',
86 'ldap_attr_login': '', # <----- missing required input
87 'ldap_attr_firstname': '',
88 'ldap_attr_lastname': '',
89 'ldap_attr_email': ''})
73
90
74 response.mustcontain("""<span class="error-message">The LDAP Login"""
91 response.mustcontain("""<span class="error-message">The LDAP Login"""
75 """ attribute of the CN must be specified""")
92 """ attribute of the CN must be specified""")
76
93
77
78 response.mustcontain("""<span class="error-message">Please """
79 """enter a number</span>""")
80
81 def test_ldap_login(self):
94 def test_ldap_login(self):
82 pass
95 pass
83
96
84 def test_ldap_login_incorrect(self):
97 def test_ldap_login_incorrect(self):
85 pass
98 pass
@@ -1,248 +1,252 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 import unittest
2 import unittest
3 import formencode
3 import formencode
4
4
5 from rhodecode.tests import *
5 from rhodecode.tests import *
6
6
7 from rhodecode.model import validators as v
7 from rhodecode.model import validators as v
8 from rhodecode.model.users_group import UserGroupModel
8 from rhodecode.model.users_group import UserGroupModel
9
9
10 from rhodecode.model.meta import Session
10 from rhodecode.model.meta import Session
11 from rhodecode.model.repos_group import ReposGroupModel
11 from rhodecode.model.repos_group import ReposGroupModel
12 from rhodecode.config.routing import ADMIN_PREFIX
12 from rhodecode.config.routing import ADMIN_PREFIX
13 from rhodecode.model.db import ChangesetStatus, Repository
13 from rhodecode.model.db import ChangesetStatus, Repository
14 from rhodecode.model.changeset_status import ChangesetStatusModel
14 from rhodecode.model.changeset_status import ChangesetStatusModel
15
15
16
16
17 class TestReposGroups(unittest.TestCase):
17 class TestReposGroups(unittest.TestCase):
18
18
19 def setUp(self):
19 def setUp(self):
20 pass
20 pass
21
21
22 def tearDown(self):
22 def tearDown(self):
23 Session.remove()
23 Session.remove()
24
24
25 def test_Message_extractor(self):
25 def test_Message_extractor(self):
26 validator = v.ValidUsername()
26 validator = v.ValidUsername()
27 self.assertRaises(formencode.Invalid, validator.to_python, 'default')
27 self.assertRaises(formencode.Invalid, validator.to_python, 'default')
28
28
29 class StateObj(object):
29 class StateObj(object):
30 pass
30 pass
31
31
32 self.assertRaises(formencode.Invalid,
32 self.assertRaises(formencode.Invalid,
33 validator.to_python, 'default', StateObj)
33 validator.to_python, 'default', StateObj)
34
34
35 def test_ValidUsername(self):
35 def test_ValidUsername(self):
36 validator = v.ValidUsername()
36 validator = v.ValidUsername()
37
37
38 self.assertRaises(formencode.Invalid, validator.to_python, 'default')
38 self.assertRaises(formencode.Invalid, validator.to_python, 'default')
39 self.assertRaises(formencode.Invalid, validator.to_python, 'new_user')
39 self.assertRaises(formencode.Invalid, validator.to_python, 'new_user')
40 self.assertRaises(formencode.Invalid, validator.to_python, '.,')
40 self.assertRaises(formencode.Invalid, validator.to_python, '.,')
41 self.assertRaises(formencode.Invalid, validator.to_python,
41 self.assertRaises(formencode.Invalid, validator.to_python,
42 TEST_USER_ADMIN_LOGIN)
42 TEST_USER_ADMIN_LOGIN)
43 self.assertEqual('test', validator.to_python('test'))
43 self.assertEqual('test', validator.to_python('test'))
44
44
45 validator = v.ValidUsername(edit=True, old_data={'user_id': 1})
45 validator = v.ValidUsername(edit=True, old_data={'user_id': 1})
46
46
47 def test_ValidRepoUser(self):
47 def test_ValidRepoUser(self):
48 validator = v.ValidRepoUser()
48 validator = v.ValidRepoUser()
49 self.assertRaises(formencode.Invalid, validator.to_python, 'nouser')
49 self.assertRaises(formencode.Invalid, validator.to_python, 'nouser')
50 self.assertEqual(TEST_USER_ADMIN_LOGIN,
50 self.assertEqual(TEST_USER_ADMIN_LOGIN,
51 validator.to_python(TEST_USER_ADMIN_LOGIN))
51 validator.to_python(TEST_USER_ADMIN_LOGIN))
52
52
53 def test_ValidUserGroup(self):
53 def test_ValidUserGroup(self):
54 validator = v.ValidUserGroup()
54 validator = v.ValidUserGroup()
55 self.assertRaises(formencode.Invalid, validator.to_python, 'default')
55 self.assertRaises(formencode.Invalid, validator.to_python, 'default')
56 self.assertRaises(formencode.Invalid, validator.to_python, '.,')
56 self.assertRaises(formencode.Invalid, validator.to_python, '.,')
57
57
58 gr = UserGroupModel().create('test')
58 gr = UserGroupModel().create('test')
59 gr2 = UserGroupModel().create('tes2')
59 gr2 = UserGroupModel().create('tes2')
60 Session.commit()
60 Session.commit()
61 self.assertRaises(formencode.Invalid, validator.to_python, 'test')
61 self.assertRaises(formencode.Invalid, validator.to_python, 'test')
62 assert gr.users_group_id != None
62 assert gr.users_group_id != None
63 validator = v.ValidUserGroup(edit=True,
63 validator = v.ValidUserGroup(edit=True,
64 old_data={'users_group_id':
64 old_data={'users_group_id':
65 gr2.users_group_id})
65 gr2.users_group_id})
66
66
67 self.assertRaises(formencode.Invalid, validator.to_python, 'test')
67 self.assertRaises(formencode.Invalid, validator.to_python, 'test')
68 self.assertRaises(formencode.Invalid, validator.to_python, 'TesT')
68 self.assertRaises(formencode.Invalid, validator.to_python, 'TesT')
69 self.assertRaises(formencode.Invalid, validator.to_python, 'TEST')
69 self.assertRaises(formencode.Invalid, validator.to_python, 'TEST')
70 UserGroupModel().delete(gr)
70 UserGroupModel().delete(gr)
71 UserGroupModel().delete(gr2)
71 UserGroupModel().delete(gr2)
72 Session.commit()
72 Session.commit()
73
73
74 def test_ValidReposGroup(self):
74 def test_ValidReposGroup(self):
75 validator = v.ValidReposGroup()
75 validator = v.ValidReposGroup()
76 model = ReposGroupModel()
76 model = ReposGroupModel()
77 self.assertRaises(formencode.Invalid, validator.to_python,
77 self.assertRaises(formencode.Invalid, validator.to_python,
78 {'group_name': HG_REPO, })
78 {'group_name': HG_REPO, })
79 gr = model.create(group_name='test_gr', group_description='desc',
79 gr = model.create(group_name='test_gr', group_description='desc',
80 parent=None,
80 parent=None,
81 just_db=True,
81 just_db=True,
82 owner=TEST_USER_ADMIN_LOGIN)
82 owner=TEST_USER_ADMIN_LOGIN)
83 self.assertRaises(formencode.Invalid,
83 self.assertRaises(formencode.Invalid,
84 validator.to_python, {'group_name': gr.group_name, })
84 validator.to_python, {'group_name': gr.group_name, })
85
85
86 validator = v.ValidReposGroup(edit=True,
86 validator = v.ValidReposGroup(edit=True,
87 old_data={'group_id': gr.group_id})
87 old_data={'group_id': gr.group_id})
88 self.assertRaises(formencode.Invalid,
88 self.assertRaises(formencode.Invalid,
89 validator.to_python, {
89 validator.to_python, {
90 'group_name': gr.group_name + 'n',
90 'group_name': gr.group_name + 'n',
91 'group_parent_id': gr.group_id
91 'group_parent_id': gr.group_id
92 })
92 })
93 model.delete(gr)
93 model.delete(gr)
94
94
95 def test_ValidPassword(self):
95 def test_ValidPassword(self):
96 validator = v.ValidPassword()
96 validator = v.ValidPassword()
97 self.assertEqual('lol', validator.to_python('lol'))
97 self.assertEqual('lol', validator.to_python('lol'))
98 self.assertEqual(None, validator.to_python(None))
98 self.assertEqual(None, validator.to_python(None))
99 self.assertRaises(formencode.Invalid, validator.to_python, 'Δ…Δ‡ΕΌΕΊ')
99 self.assertRaises(formencode.Invalid, validator.to_python, 'Δ…Δ‡ΕΌΕΊ')
100
100
101 def test_ValidPasswordsMatch(self):
101 def test_ValidPasswordsMatch(self):
102 validator = v.ValidPasswordsMatch()
102 validator = v.ValidPasswordsMatch()
103 self.assertRaises(formencode.Invalid,
103 self.assertRaises(formencode.Invalid,
104 validator.to_python, {'password': 'pass',
104 validator.to_python, {'password': 'pass',
105 'password_confirmation': 'pass2'})
105 'password_confirmation': 'pass2'})
106
106
107 self.assertRaises(formencode.Invalid,
107 self.assertRaises(formencode.Invalid,
108 validator.to_python, {'new_password': 'pass',
108 validator.to_python, {'new_password': 'pass',
109 'password_confirmation': 'pass2'})
109 'password_confirmation': 'pass2'})
110
110
111 self.assertEqual({'new_password': 'pass',
111 self.assertEqual({'new_password': 'pass',
112 'password_confirmation': 'pass'},
112 'password_confirmation': 'pass'},
113 validator.to_python({'new_password': 'pass',
113 validator.to_python({'new_password': 'pass',
114 'password_confirmation': 'pass'}))
114 'password_confirmation': 'pass'}))
115
115
116 self.assertEqual({'password': 'pass',
116 self.assertEqual({'password': 'pass',
117 'password_confirmation': 'pass'},
117 'password_confirmation': 'pass'},
118 validator.to_python({'password': 'pass',
118 validator.to_python({'password': 'pass',
119 'password_confirmation': 'pass'}))
119 'password_confirmation': 'pass'}))
120
120
121 def test_ValidAuth(self):
121 def test_ValidAuth(self):
122 validator = v.ValidAuth()
122 validator = v.ValidAuth()
123 valid_creds = {
123 valid_creds = {
124 'username': TEST_USER_REGULAR2_LOGIN,
124 'username': TEST_USER_REGULAR2_LOGIN,
125 'password': TEST_USER_REGULAR2_PASS,
125 'password': TEST_USER_REGULAR2_PASS,
126 }
126 }
127 invalid_creds = {
127 invalid_creds = {
128 'username': 'err',
128 'username': 'err',
129 'password': 'err',
129 'password': 'err',
130 }
130 }
131 self.assertEqual(valid_creds, validator.to_python(valid_creds))
131 self.assertEqual(valid_creds, validator.to_python(valid_creds))
132 self.assertRaises(formencode.Invalid,
132 self.assertRaises(formencode.Invalid,
133 validator.to_python, invalid_creds)
133 validator.to_python, invalid_creds)
134
134
135 def test_ValidAuthToken(self):
135 def test_ValidAuthToken(self):
136 validator = v.ValidAuthToken()
136 validator = v.ValidAuthToken()
137 # this is untestable without a threadlocal
137 # this is untestable without a threadlocal
138 # self.assertRaises(formencode.Invalid,
138 # self.assertRaises(formencode.Invalid,
139 # validator.to_python, 'BadToken')
139 # validator.to_python, 'BadToken')
140 validator
140 validator
141
141
142 def test_ValidRepoName(self):
142 def test_ValidRepoName(self):
143 validator = v.ValidRepoName()
143 validator = v.ValidRepoName()
144
144
145 self.assertRaises(formencode.Invalid,
145 self.assertRaises(formencode.Invalid,
146 validator.to_python, {'repo_name': ''})
146 validator.to_python, {'repo_name': ''})
147
147
148 self.assertRaises(formencode.Invalid,
148 self.assertRaises(formencode.Invalid,
149 validator.to_python, {'repo_name': HG_REPO})
149 validator.to_python, {'repo_name': HG_REPO})
150
150
151 gr = ReposGroupModel().create(group_name='group_test',
151 gr = ReposGroupModel().create(group_name='group_test',
152 group_description='desc',
152 group_description='desc',
153 parent=None,
153 parent=None,
154 owner=TEST_USER_ADMIN_LOGIN)
154 owner=TEST_USER_ADMIN_LOGIN)
155 self.assertRaises(formencode.Invalid,
155 self.assertRaises(formencode.Invalid,
156 validator.to_python, {'repo_name': gr.group_name})
156 validator.to_python, {'repo_name': gr.group_name})
157
157
158 #TODO: write an error case for that ie. create a repo withinh a group
158 #TODO: write an error case for that ie. create a repo withinh a group
159 # self.assertRaises(formencode.Invalid,
159 # self.assertRaises(formencode.Invalid,
160 # validator.to_python, {'repo_name': 'some',
160 # validator.to_python, {'repo_name': 'some',
161 # 'repo_group': gr.group_id})
161 # 'repo_group': gr.group_id})
162
162
163 def test_ValidForkName(self):
163 def test_ValidForkName(self):
164 # this uses ValidRepoName validator
164 # this uses ValidRepoName validator
165 assert True
165 assert True
166
166
167 @parameterized.expand([
167 @parameterized.expand([
168 ('test', 'test'), ('lolz!', 'lolz'), (' aavv', 'aavv'),
168 ('test', 'test'), ('lolz!', 'lolz'), (' aavv', 'aavv'),
169 ('ala ma kota', 'ala-ma-kota'), ('@nooo', 'nooo'),
169 ('ala ma kota', 'ala-ma-kota'), ('@nooo', 'nooo'),
170 ('$!haha lolz !', 'haha-lolz'), ('$$$$$', ''), ('{}OK!', 'OK'),
170 ('$!haha lolz !', 'haha-lolz'), ('$$$$$', ''), ('{}OK!', 'OK'),
171 ('/]re po', 're-po')])
171 ('/]re po', 're-po')])
172 def test_SlugifyName(self, name, expected):
172 def test_SlugifyName(self, name, expected):
173 validator = v.SlugifyName()
173 validator = v.SlugifyName()
174 self.assertEqual(expected, validator.to_python(name))
174 self.assertEqual(expected, validator.to_python(name))
175
175
176 def test_ValidCloneUri(self):
176 def test_ValidCloneUri(self):
177 #TODO: write this one
177 #TODO: write this one
178 pass
178 pass
179
179
180 def test_ValidForkType(self):
180 def test_ValidForkType(self):
181 validator = v.ValidForkType(old_data={'repo_type': 'hg'})
181 validator = v.ValidForkType(old_data={'repo_type': 'hg'})
182 self.assertEqual('hg', validator.to_python('hg'))
182 self.assertEqual('hg', validator.to_python('hg'))
183 self.assertRaises(formencode.Invalid, validator.to_python, 'git')
183 self.assertRaises(formencode.Invalid, validator.to_python, 'git')
184
184
185 def test_ValidPerms(self):
185 def test_ValidPerms(self):
186 #TODO: write this one
186 #TODO: write this one
187 pass
187 pass
188
188
189 def test_ValidSettings(self):
189 def test_ValidSettings(self):
190 validator = v.ValidSettings()
190 validator = v.ValidSettings()
191 self.assertEqual({'pass': 'pass'},
191 self.assertEqual({'pass': 'pass'},
192 validator.to_python(value={'user': 'test',
192 validator.to_python(value={'user': 'test',
193 'pass': 'pass'}))
193 'pass': 'pass'}))
194
194
195 self.assertEqual({'user2': 'test', 'pass': 'pass'},
195 self.assertEqual({'user2': 'test', 'pass': 'pass'},
196 validator.to_python(value={'user2': 'test',
196 validator.to_python(value={'user2': 'test',
197 'pass': 'pass'}))
197 'pass': 'pass'}))
198
198
199 def test_ValidPath(self):
199 def test_ValidPath(self):
200 validator = v.ValidPath()
200 validator = v.ValidPath()
201 self.assertEqual(TESTS_TMP_PATH,
201 self.assertEqual(TESTS_TMP_PATH,
202 validator.to_python(TESTS_TMP_PATH))
202 validator.to_python(TESTS_TMP_PATH))
203 self.assertRaises(formencode.Invalid, validator.to_python,
203 self.assertRaises(formencode.Invalid, validator.to_python,
204 '/no_such_dir')
204 '/no_such_dir')
205
205
206 def test_UniqSystemEmail(self):
206 def test_UniqSystemEmail(self):
207 validator = v.UniqSystemEmail(old_data={})
207 validator = v.UniqSystemEmail(old_data={})
208
208
209 self.assertEqual('mail@python.org',
209 self.assertEqual('mail@python.org',
210 validator.to_python('MaiL@Python.org'))
210 validator.to_python('MaiL@Python.org'))
211
211
212 email = TEST_USER_REGULAR2_EMAIL
212 email = TEST_USER_REGULAR2_EMAIL
213 self.assertRaises(formencode.Invalid, validator.to_python, email)
213 self.assertRaises(formencode.Invalid, validator.to_python, email)
214
214
215 def test_ValidSystemEmail(self):
215 def test_ValidSystemEmail(self):
216 validator = v.ValidSystemEmail()
216 validator = v.ValidSystemEmail()
217 email = TEST_USER_REGULAR2_EMAIL
217 email = TEST_USER_REGULAR2_EMAIL
218
218
219 self.assertEqual(email, validator.to_python(email))
219 self.assertEqual(email, validator.to_python(email))
220 self.assertRaises(formencode.Invalid, validator.to_python, 'err')
220 self.assertRaises(formencode.Invalid, validator.to_python, 'err')
221
221
222 def test_LdapLibValidator(self):
222 def test_LdapLibValidator(self):
223 validator = v.LdapLibValidator()
223 if ldap_lib_installed:
224 self.assertRaises(v.LdapImportError, validator.to_python, 'err')
224 validator = v.LdapLibValidator()
225 self.assertEqual("DN", validator.to_python('DN'))
226 else:
227 validator = v.LdapLibValidator()
228 self.assertRaises(v.LdapImportError, validator.to_python, 'err')
225
229
226 def test_AttrLoginValidator(self):
230 def test_AttrLoginValidator(self):
227 validator = v.AttrLoginValidator()
231 validator = v.AttrLoginValidator()
228 self.assertRaises(formencode.Invalid, validator.to_python, 123)
232 self.assertEqual('DN_attr', validator.to_python('DN_attr'))
229
233
230 def test_NotReviewedRevisions(self):
234 def test_NotReviewedRevisions(self):
231 repo_id = Repository.get_by_repo_name(HG_REPO).repo_id
235 repo_id = Repository.get_by_repo_name(HG_REPO).repo_id
232 validator = v.NotReviewedRevisions(repo_id)
236 validator = v.NotReviewedRevisions(repo_id)
233 rev = '0' * 40
237 rev = '0' * 40
234 # add status for a rev, that should throw an error because it is already
238 # add status for a rev, that should throw an error because it is already
235 # reviewed
239 # reviewed
236 new_status = ChangesetStatus()
240 new_status = ChangesetStatus()
237 new_status.author = ChangesetStatusModel()._get_user(TEST_USER_ADMIN_LOGIN)
241 new_status.author = ChangesetStatusModel()._get_user(TEST_USER_ADMIN_LOGIN)
238 new_status.repo = ChangesetStatusModel()._get_repo(HG_REPO)
242 new_status.repo = ChangesetStatusModel()._get_repo(HG_REPO)
239 new_status.status = ChangesetStatus.STATUS_APPROVED
243 new_status.status = ChangesetStatus.STATUS_APPROVED
240 new_status.comment = None
244 new_status.comment = None
241 new_status.revision = rev
245 new_status.revision = rev
242 Session().add(new_status)
246 Session().add(new_status)
243 Session().commit()
247 Session().commit()
244 try:
248 try:
245 self.assertRaises(formencode.Invalid, validator.to_python, [rev])
249 self.assertRaises(formencode.Invalid, validator.to_python, [rev])
246 finally:
250 finally:
247 Session().delete(new_status)
251 Session().delete(new_status)
248 Session().commit()
252 Session().commit()
General Comments 0
You need to be logged in to leave comments. Login now