Show More
@@ -158,9 +158,9 b' INPUT::' | |||||
158 | args : { |
|
158 | args : { | |
159 | "username" : "<username>", |
|
159 | "username" : "<username>", | |
160 | "password" : "<password>", |
|
160 | "password" : "<password>", | |
161 |
" |
|
161 | "email" : "<useremail>", | |
162 |
" |
|
162 | "firstname" : "<firstname> = None", | |
163 |
" |
|
163 | "lastname" : "<lastname> = None", | |
164 | "active" : "<bool> = True", |
|
164 | "active" : "<bool> = True", | |
165 | "admin" : "<bool> = False", |
|
165 | "admin" : "<bool> = False", | |
166 | "ldap_dn" : "<ldap_dn> = None" |
|
166 | "ldap_dn" : "<ldap_dn> = None" |
@@ -35,6 +35,7 b' news' | |||||
35 | based on user defined regular expression |
|
35 | based on user defined regular expression | |
36 | - added linking of changesets in commit messages |
|
36 | - added linking of changesets in commit messages | |
37 | - new compact changelog with expandable commit messages |
|
37 | - new compact changelog with expandable commit messages | |
|
38 | - firstname and lastname are optional in user creation | |||
38 |
|
39 | |||
39 | fixes |
|
40 | fixes | |
40 | ----- |
|
41 | ----- |
@@ -131,17 +131,17 b' class ApiController(JSONRPCController):' | |||||
131 | return result |
|
131 | return result | |
132 |
|
132 | |||
133 | @HasPermissionAllDecorator('hg.admin') |
|
133 | @HasPermissionAllDecorator('hg.admin') | |
134 | def create_user(self, apiuser, username, password, firstname, |
|
134 | def create_user(self, apiuser, username, password, email, firstname=None, | |
135 |
lastname |
|
135 | lastname=None, active=True, admin=False, ldap_dn=None): | |
136 | """ |
|
136 | """ | |
137 | Create new user or updates current one |
|
137 | Create new user or updates current one | |
138 |
|
138 | |||
139 | :param apiuser: |
|
139 | :param apiuser: | |
140 | :param username: |
|
140 | :param username: | |
141 | :param password: |
|
141 | :param password: | |
|
142 | :param email: | |||
142 | :param name: |
|
143 | :param name: | |
143 | :param lastname: |
|
144 | :param lastname: | |
144 | :param email: |
|
|||
145 | :param active: |
|
145 | :param active: | |
146 | :param admin: |
|
146 | :param admin: | |
147 | :param ldap_dn: |
|
147 | :param ldap_dn: |
@@ -129,6 +129,7 b' def get_crypt_password(password):' | |||||
129 | def check_password(password, hashed): |
|
129 | def check_password(password, hashed): | |
130 | return RhodeCodeCrypto.hash_check(password, hashed) |
|
130 | return RhodeCodeCrypto.hash_check(password, hashed) | |
131 |
|
131 | |||
|
132 | ||||
132 | def generate_api_key(str_, salt=None): |
|
133 | def generate_api_key(str_, salt=None): | |
133 | """ |
|
134 | """ | |
134 | Generates API KEY from given string |
|
135 | Generates API KEY from given string | |
@@ -237,6 +238,7 b' def authenticate(username, password):' | |||||
237 | pass |
|
238 | pass | |
238 | return False |
|
239 | return False | |
239 |
|
240 | |||
|
241 | ||||
240 | def login_container_auth(username): |
|
242 | def login_container_auth(username): | |
241 | user = User.get_by_username(username) |
|
243 | user = User.get_by_username(username) | |
242 | if user is None: |
|
244 | if user is None: | |
@@ -260,6 +262,7 b' def login_container_auth(username):' | |||||
260 | user.username) |
|
262 | user.username) | |
261 | return user |
|
263 | return user | |
262 |
|
264 | |||
|
265 | ||||
263 | def get_container_username(environ, config): |
|
266 | def get_container_username(environ, config): | |
264 | username = None |
|
267 | username = None | |
265 |
|
268 | |||
@@ -278,6 +281,7 b' def get_container_username(environ, conf' | |||||
278 |
|
281 | |||
279 | return username |
|
282 | return username | |
280 |
|
283 | |||
|
284 | ||||
281 | class AuthUser(object): |
|
285 | class AuthUser(object): | |
282 | """ |
|
286 | """ | |
283 | A simple object that handles all attributes of user in RhodeCode |
|
287 | A simple object that handles all attributes of user in RhodeCode | |
@@ -302,6 +306,7 b' class AuthUser(object):' | |||||
302 | self.permissions = {} |
|
306 | self.permissions = {} | |
303 | self._api_key = api_key |
|
307 | self._api_key = api_key | |
304 | self.propagate_data() |
|
308 | self.propagate_data() | |
|
309 | self._instance = None | |||
305 |
|
310 | |||
306 | def propagate_data(self): |
|
311 | def propagate_data(self): | |
307 | user_model = UserModel() |
|
312 | user_model = UserModel() | |
@@ -350,10 +355,6 b' class AuthUser(object):' | |||||
350 | def is_admin(self): |
|
355 | def is_admin(self): | |
351 | return self.admin |
|
356 | return self.admin | |
352 |
|
357 | |||
353 | @property |
|
|||
354 | def full_contact(self): |
|
|||
355 | return '%s %s <%s>' % (self.name, self.lastname, self.email) |
|
|||
356 |
|
||||
357 | def __repr__(self): |
|
358 | def __repr__(self): | |
358 | return "<AuthUser('id:%s:%s|%s')>" % (self.user_id, self.username, |
|
359 | return "<AuthUser('id:%s:%s|%s')>" % (self.user_id, self.username, | |
359 | self.is_authenticated) |
|
360 | self.is_authenticated) | |
@@ -363,9 +364,9 b' class AuthUser(object):' | |||||
363 | self.is_authenticated = authenticated |
|
364 | self.is_authenticated = authenticated | |
364 |
|
365 | |||
365 | def get_cookie_store(self): |
|
366 | def get_cookie_store(self): | |
366 | return {'username':self.username, |
|
367 | return {'username': self.username, | |
367 | 'user_id': self.user_id, |
|
368 | 'user_id': self.user_id, | |
368 | 'is_authenticated':self.is_authenticated} |
|
369 | 'is_authenticated': self.is_authenticated} | |
369 |
|
370 | |||
370 | @classmethod |
|
371 | @classmethod | |
371 | def from_cookie_store(cls, cookie_store): |
|
372 | def from_cookie_store(cls, cookie_store): | |
@@ -374,6 +375,7 b' class AuthUser(object):' | |||||
374 | api_key = cookie_store.get('api_key') |
|
375 | api_key = cookie_store.get('api_key') | |
375 | return AuthUser(user_id, api_key, username) |
|
376 | return AuthUser(user_id, api_key, username) | |
376 |
|
377 | |||
|
378 | ||||
377 | def set_available_permissions(config): |
|
379 | def set_available_permissions(config): | |
378 | """ |
|
380 | """ | |
379 | This function will propagate pylons globals with all available defined |
|
381 | This function will propagate pylons globals with all available defined | |
@@ -388,7 +390,7 b' def set_available_permissions(config):' | |||||
388 | try: |
|
390 | try: | |
389 | sa = meta.Session |
|
391 | sa = meta.Session | |
390 | all_perms = sa.query(Permission).all() |
|
392 | all_perms = sa.query(Permission).all() | |
391 | except: |
|
393 | except Exception: | |
392 | pass |
|
394 | pass | |
393 | finally: |
|
395 | finally: | |
394 | meta.Session.remove() |
|
396 | meta.Session.remove() |
@@ -299,6 +299,11 b' class User(Base, BaseModel):' | |||||
299 | return '%s %s' % (self.name, self.lastname) |
|
299 | return '%s %s' % (self.name, self.lastname) | |
300 |
|
300 | |||
301 | @property |
|
301 | @property | |
|
302 | def full_name_or_username(self): | |||
|
303 | return ('%s %s' % (self.name, self.lastname) | |||
|
304 | if (self.name and self.lastname) else self.username) | |||
|
305 | ||||
|
306 | @property | |||
302 | def full_contact(self): |
|
307 | def full_contact(self): | |
303 | return '%s %s <%s>' % (self.name, self.lastname, self.email) |
|
308 | return '%s %s <%s>' % (self.name, self.lastname, self.email) | |
304 |
|
309 | |||
@@ -354,8 +359,13 b' class User(Base, BaseModel):' | |||||
354 | log.debug('updated user %s lastlogin', self.username) |
|
359 | log.debug('updated user %s lastlogin', self.username) | |
355 |
|
360 | |||
356 | def __json__(self): |
|
361 | def __json__(self): | |
357 |
return dict( |
|
362 | return dict( | |
358 | full_name=self.full_name) |
|
363 | email=self.email, | |
|
364 | full_name=self.full_name, | |||
|
365 | full_name_or_username=self.full_name_or_username, | |||
|
366 | short_contact=self.short_contact, | |||
|
367 | full_contact=self.full_contact | |||
|
368 | ) | |||
359 |
|
369 | |||
360 |
|
370 | |||
361 | class UserLog(Base, BaseModel): |
|
371 | class UserLog(Base, BaseModel): |
@@ -51,13 +51,17 b' class State_obj(object):' | |||||
51 | # VALIDATORS |
|
51 | # VALIDATORS | |
52 | #============================================================================== |
|
52 | #============================================================================== | |
53 | class ValidAuthToken(formencode.validators.FancyValidator): |
|
53 | class ValidAuthToken(formencode.validators.FancyValidator): | |
54 | messages = {'invalid_token':_('Token mismatch')} |
|
54 | messages = {'invalid_token': _('Token mismatch')} | |
55 |
|
55 | |||
56 | def validate_python(self, value, state): |
|
56 | def validate_python(self, value, state): | |
57 |
|
57 | |||
58 | if value != authentication_token(): |
|
58 | if value != authentication_token(): | |
59 |
raise formencode.Invalid( |
|
59 | raise formencode.Invalid( | |
60 | search_number=value), value, state) |
|
60 | self.message('invalid_token', | |
|
61 | state, search_number=value), | |||
|
62 | value, | |||
|
63 | state | |||
|
64 | ) | |||
61 |
|
65 | |||
62 |
|
66 | |||
63 | def ValidUsername(edit, old_data): |
|
67 | def ValidUsername(edit, old_data): | |
@@ -77,11 +81,13 b' def ValidUsername(edit, old_data):' | |||||
77 | 'exists') , value, state) |
|
81 | 'exists') , value, state) | |
78 |
|
82 | |||
79 | if re.match(r'^[a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]+$', value) is None: |
|
83 | if re.match(r'^[a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]+$', value) is None: | |
80 |
raise formencode.Invalid( |
|
84 | raise formencode.Invalid( | |
81 |
|
|
85 | _('Username may only contain alphanumeric characters ' | |
82 |
|
|
86 | 'underscores, periods or dashes and must begin with ' | |
83 | 'and must begin with alphanumeric ' |
|
87 | 'alphanumeric character'), | |
84 | 'character'), value, state) |
|
88 | value, | |
|
89 | state | |||
|
90 | ) | |||
85 |
|
91 | |||
86 | return _ValidUsername |
|
92 | return _ValidUsername | |
87 |
|
93 | |||
@@ -103,15 +109,17 b' def ValidUsersGroup(edit, old_data):' | |||||
103 | if UsersGroup.get_by_group_name(value, cache=False, |
|
109 | if UsersGroup.get_by_group_name(value, cache=False, | |
104 | case_insensitive=True): |
|
110 | case_insensitive=True): | |
105 | raise formencode.Invalid(_('This users group ' |
|
111 | raise formencode.Invalid(_('This users group ' | |
106 |
'already exists') |
|
112 | 'already exists'), value, | |
107 | state) |
|
113 | state) | |
108 |
|
114 | |||
109 | if re.match(r'^[a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]+$', value) is None: |
|
115 | if re.match(r'^[a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]+$', value) is None: | |
110 |
raise formencode.Invalid( |
|
116 | raise formencode.Invalid( | |
111 |
|
|
117 | _('RepoGroup name may only contain alphanumeric characters ' | |
112 |
|
|
118 | 'underscores, periods or dashes and must begin with ' | |
113 | 'and must begin with alphanumeric ' |
|
119 | 'alphanumeric character'), | |
114 | 'character'), value, state) |
|
120 | value, | |
|
121 | state | |||
|
122 | ) | |||
115 |
|
123 | |||
116 | return _ValidUsersGroup |
|
124 | return _ValidUsersGroup | |
117 |
|
125 | |||
@@ -177,32 +185,35 b' class ValidPassword(formencode.validator' | |||||
177 |
|
185 | |||
178 | def to_python(self, value, state): |
|
186 | def to_python(self, value, state): | |
179 |
|
187 | |||
180 | if value: |
|
188 | if not value: | |
|
189 | return | |||
181 |
|
190 | |||
182 |
|
|
191 | if value.get('password'): | |
183 |
|
|
192 | try: | |
184 |
|
|
193 | value['password'] = get_crypt_password(value['password']) | |
185 |
|
|
194 | except UnicodeEncodeError: | |
186 |
|
|
195 | e_dict = {'password': _('Invalid characters in password')} | |
187 |
|
|
196 | raise formencode.Invalid('', value, state, error_dict=e_dict) | |
188 |
|
197 | |||
189 |
|
|
198 | if value.get('password_confirmation'): | |
190 |
|
|
199 | try: | |
191 |
|
|
200 | value['password_confirmation'] = \ | |
192 |
|
|
201 | get_crypt_password(value['password_confirmation']) | |
193 |
|
|
202 | except UnicodeEncodeError: | |
194 | e_dict = {'password_confirmation':_('Invalid characters in password')} |
|
203 | e_dict = { | |
195 | raise formencode.Invalid('', value, state, error_dict=e_dict) |
|
204 | 'password_confirmation': _('Invalid characters in password') | |
|
205 | } | |||
|
206 | raise formencode.Invalid('', value, state, error_dict=e_dict) | |||
196 |
|
207 | |||
197 |
|
|
208 | if value.get('new_password'): | |
198 |
|
|
209 | try: | |
199 |
|
|
210 | value['new_password'] = \ | |
200 |
|
|
211 | get_crypt_password(value['new_password']) | |
201 |
|
|
212 | except UnicodeEncodeError: | |
202 |
|
|
213 | e_dict = {'new_password': _('Invalid characters in password')} | |
203 |
|
|
214 | raise formencode.Invalid('', value, state, error_dict=e_dict) | |
204 |
|
215 | |||
205 |
|
|
216 | return value | |
206 |
|
217 | |||
207 |
|
218 | |||
208 | class ValidPasswordsMatch(formencode.validators.FancyValidator): |
|
219 | class ValidPasswordsMatch(formencode.validators.FancyValidator): | |
@@ -224,9 +235,9 b' class ValidAuth(formencode.validators.Fa' | |||||
224 | } |
|
235 | } | |
225 |
|
236 | |||
226 | # error mapping |
|
237 | # error mapping | |
227 | e_dict = {'username':messages['invalid_login'], |
|
238 | e_dict = {'username': messages['invalid_login'], | |
228 | 'password':messages['invalid_password']} |
|
239 | 'password': messages['invalid_password']} | |
229 | e_dict_disable = {'username':messages['disabled_account']} |
|
240 | e_dict_disable = {'username': messages['disabled_account']} | |
230 |
|
241 | |||
231 | def validate_python(self, value, state): |
|
242 | def validate_python(self, value, state): | |
232 | password = value['password'] |
|
243 | password = value['password'] | |
@@ -238,15 +249,19 b' class ValidAuth(formencode.validators.Fa' | |||||
238 | else: |
|
249 | else: | |
239 | if user and user.active is False: |
|
250 | if user and user.active is False: | |
240 | log.warning('user %s is disabled', username) |
|
251 | log.warning('user %s is disabled', username) | |
241 |
raise formencode.Invalid( |
|
252 | raise formencode.Invalid( | |
242 | state=State_obj), |
|
253 | self.message('disabled_account', | |
243 | value, state, |
|
254 | state=State_obj), | |
244 | error_dict=self.e_dict_disable) |
|
255 | value, state, | |
|
256 | error_dict=self.e_dict_disable | |||
|
257 | ) | |||
245 | else: |
|
258 | else: | |
246 | log.warning('user %s not authenticated', username) |
|
259 | log.warning('user %s not authenticated', username) | |
247 |
raise formencode.Invalid( |
|
260 | raise formencode.Invalid( | |
248 | state=State_obj), value, state, |
|
261 | self.message('invalid_password', | |
249 | error_dict=self.e_dict) |
|
262 | state=State_obj), value, state, | |
|
263 | error_dict=self.e_dict | |||
|
264 | ) | |||
250 |
|
265 | |||
251 |
|
266 | |||
252 | class ValidRepoUser(formencode.validators.FancyValidator): |
|
267 | class ValidRepoUser(formencode.validators.FancyValidator): | |
@@ -272,7 +287,6 b' def ValidRepoName(edit, old_data):' | |||||
272 | e_dict = {'repo_name': _('This repository name is disallowed')} |
|
287 | e_dict = {'repo_name': _('This repository name is disallowed')} | |
273 | raise formencode.Invalid('', value, state, error_dict=e_dict) |
|
288 | raise formencode.Invalid('', value, state, error_dict=e_dict) | |
274 |
|
289 | |||
275 |
|
||||
276 | if value.get('repo_group'): |
|
290 | if value.get('repo_group'): | |
277 | gr = RepoGroup.get(value.get('repo_group')) |
|
291 | gr = RepoGroup.get(value.get('repo_group')) | |
278 | group_path = gr.full_path |
|
292 | group_path = gr.full_path | |
@@ -285,7 +299,6 b' def ValidRepoName(edit, old_data):' | |||||
285 | group_path = '' |
|
299 | group_path = '' | |
286 | repo_name_full = repo_name |
|
300 | repo_name_full = repo_name | |
287 |
|
301 | |||
288 |
|
||||
289 | value['repo_name_full'] = repo_name_full |
|
302 | value['repo_name_full'] = repo_name_full | |
290 | rename = old_data.get('repo_name') != repo_name_full |
|
303 | rename = old_data.get('repo_name') != repo_name_full | |
291 | create = not edit |
|
304 | create = not edit | |
@@ -293,20 +306,22 b' def ValidRepoName(edit, old_data):' | |||||
293 |
|
306 | |||
294 | if group_path != '': |
|
307 | if group_path != '': | |
295 | if Repository.get_by_repo_name(repo_name_full): |
|
308 | if Repository.get_by_repo_name(repo_name_full): | |
296 |
e_dict = { |
|
309 | e_dict = { | |
297 | 'exists in a group "%s"') % |
|
310 | 'repo_name': _('This repository already exists in ' | |
298 |
gr.group_name |
|
311 | 'a group "%s"') % gr.group_name | |
|
312 | } | |||
299 | raise formencode.Invalid('', value, state, |
|
313 | raise formencode.Invalid('', value, state, | |
300 | error_dict=e_dict) |
|
314 | error_dict=e_dict) | |
301 | elif RepoGroup.get_by_group_name(repo_name_full): |
|
315 | elif RepoGroup.get_by_group_name(repo_name_full): | |
302 |
e_dict = { |
|
316 | e_dict = { | |
303 | ' name already "%s"') % |
|
317 | 'repo_name': _('There is a group with this name ' | |
304 |
repo_name_full |
|
318 | 'already "%s"') % repo_name_full | |
|
319 | } | |||
305 | raise formencode.Invalid('', value, state, |
|
320 | raise formencode.Invalid('', value, state, | |
306 | error_dict=e_dict) |
|
321 | error_dict=e_dict) | |
307 |
|
322 | |||
308 | elif Repository.get_by_repo_name(repo_name_full): |
|
323 | elif Repository.get_by_repo_name(repo_name_full): | |
309 | e_dict = {'repo_name':_('This repository ' |
|
324 | e_dict = {'repo_name': _('This repository ' | |
310 | 'already exists')} |
|
325 | 'already exists')} | |
311 | raise formencode.Invalid('', value, state, |
|
326 | raise formencode.Invalid('', value, state, | |
312 | error_dict=e_dict) |
|
327 | error_dict=e_dict) | |
@@ -341,14 +356,14 b' def ValidCloneUri():' | |||||
341 | elif value.startswith('https'): |
|
356 | elif value.startswith('https'): | |
342 | try: |
|
357 | try: | |
343 | httpsrepository(make_ui('db'), value).capabilities |
|
358 | httpsrepository(make_ui('db'), value).capabilities | |
344 |
except Exception |
|
359 | except Exception: | |
345 | log.error(traceback.format_exc()) |
|
360 | log.error(traceback.format_exc()) | |
346 | raise formencode.Invalid(_('invalid clone url'), value, |
|
361 | raise formencode.Invalid(_('invalid clone url'), value, | |
347 | state) |
|
362 | state) | |
348 | elif value.startswith('http'): |
|
363 | elif value.startswith('http'): | |
349 | try: |
|
364 | try: | |
350 | httprepository(make_ui('db'), value).capabilities |
|
365 | httprepository(make_ui('db'), value).capabilities | |
351 |
except Exception |
|
366 | except Exception: | |
352 | log.error(traceback.format_exc()) |
|
367 | log.error(traceback.format_exc()) | |
353 | raise formencode.Invalid(_('invalid clone url'), value, |
|
368 | raise formencode.Invalid(_('invalid clone url'), value, | |
354 | state) |
|
369 | state) | |
@@ -374,7 +389,7 b' def ValidForkType(old_data):' | |||||
374 |
|
389 | |||
375 |
|
390 | |||
376 | class ValidPerms(formencode.validators.FancyValidator): |
|
391 | class ValidPerms(formencode.validators.FancyValidator): | |
377 | messages = {'perm_new_member_name':_('This username or users group name' |
|
392 | messages = {'perm_new_member_name': _('This username or users group name' | |
378 | ' is not valid')} |
|
393 | ' is not valid')} | |
379 |
|
394 | |||
380 | def to_python(self, value, state): |
|
395 | def to_python(self, value, state): | |
@@ -393,8 +408,9 b' class ValidPerms(formencode.validators.F' | |||||
393 | perms_new.append((new_member, new_perm, new_type)) |
|
408 | perms_new.append((new_member, new_perm, new_type)) | |
394 | elif k.startswith('u_perm_') or k.startswith('g_perm_'): |
|
409 | elif k.startswith('u_perm_') or k.startswith('g_perm_'): | |
395 | member = k[7:] |
|
410 | member = k[7:] | |
396 | t = {'u':'user', |
|
411 | t = {'u': 'user', | |
397 |
'g':'users_group' |
|
412 | 'g': 'users_group' | |
|
413 | }[k[0]] | |||
398 | if member == 'default': |
|
414 | if member == 'default': | |
399 | if value['private']: |
|
415 | if value['private']: | |
400 | #set none for default when updating to private repo |
|
416 | #set none for default when updating to private repo | |
@@ -419,8 +435,9 b' class ValidPerms(formencode.validators.F' | |||||
419 | except Exception: |
|
435 | except Exception: | |
420 | msg = self.message('perm_new_member_name', |
|
436 | msg = self.message('perm_new_member_name', | |
421 | state=State_obj) |
|
437 | state=State_obj) | |
422 |
raise formencode.Invalid( |
|
438 | raise formencode.Invalid( | |
423 |
|
|
439 | msg, value, state, error_dict={'perm_new_member_name': msg} | |
|
440 | ) | |||
424 | return value |
|
441 | return value | |
425 |
|
442 | |||
426 |
|
443 | |||
@@ -428,9 +445,8 b' class ValidSettings(formencode.validator' | |||||
428 |
|
445 | |||
429 | def to_python(self, value, state): |
|
446 | def to_python(self, value, state): | |
430 | # settings form can't edit user |
|
447 | # settings form can't edit user | |
431 |
if |
|
448 | if 'user' in value: | |
432 | del['value']['user'] |
|
449 | del['value']['user'] | |
433 |
|
||||
434 | return value |
|
450 | return value | |
435 |
|
451 | |||
436 |
|
452 | |||
@@ -440,7 +456,7 b' class ValidPath(formencode.validators.Fa' | |||||
440 | if not os.path.isdir(value): |
|
456 | if not os.path.isdir(value): | |
441 | msg = _('This is not a valid path') |
|
457 | msg = _('This is not a valid path') | |
442 | raise formencode.Invalid(msg, value, state, |
|
458 | raise formencode.Invalid(msg, value, state, | |
443 | error_dict={'paths_root_path':msg}) |
|
459 | error_dict={'paths_root_path': msg}) | |
444 | return value |
|
460 | return value | |
445 |
|
461 | |||
446 |
|
462 | |||
@@ -448,12 +464,12 b' def UniqSystemEmail(old_data):' | |||||
448 | class _UniqSystemEmail(formencode.validators.FancyValidator): |
|
464 | class _UniqSystemEmail(formencode.validators.FancyValidator): | |
449 | def to_python(self, value, state): |
|
465 | def to_python(self, value, state): | |
450 | value = value.lower() |
|
466 | value = value.lower() | |
451 | if old_data.get('email','').lower() != value: |
|
467 | if old_data.get('email', '').lower() != value: | |
452 | user = User.get_by_email(value, case_insensitive=True) |
|
468 | user = User.get_by_email(value, case_insensitive=True) | |
453 | if user: |
|
469 | if user: | |
454 | raise formencode.Invalid( |
|
470 | raise formencode.Invalid( | |
455 |
|
|
471 | _("This e-mail address is already taken"), value, state | |
456 |
|
|
472 | ) | |
457 | return value |
|
473 | return value | |
458 |
|
474 | |||
459 | return _UniqSystemEmail |
|
475 | return _UniqSystemEmail | |
@@ -464,8 +480,9 b' class ValidSystemEmail(formencode.valida' | |||||
464 | value = value.lower() |
|
480 | value = value.lower() | |
465 | user = User.get_by_email(value, case_insensitive=True) |
|
481 | user = User.get_by_email(value, case_insensitive=True) | |
466 | if user is None: |
|
482 | if user is None: | |
467 |
raise formencode.Invalid( |
|
483 | raise formencode.Invalid( | |
468 | value, state) |
|
484 | _("This e-mail address doesn't exist."), value, state | |
|
485 | ) | |||
469 |
|
486 | |||
470 | return value |
|
487 | return value | |
471 |
|
488 | |||
@@ -486,14 +503,15 b' class AttrLoginValidator(formencode.vali' | |||||
486 | def to_python(self, value, state): |
|
503 | def to_python(self, value, state): | |
487 |
|
504 | |||
488 | if not value or not isinstance(value, (str, unicode)): |
|
505 | if not value or not isinstance(value, (str, unicode)): | |
489 |
raise formencode.Invalid( |
|
506 | raise formencode.Invalid( | |
490 | "must be specified - this is the name " |
|
507 | _("The LDAP Login attribute of the CN must be specified - " | |
491 |
|
|
508 | "this is the name of the attribute that is equivalent " | |
492 |
|
|
509 | "to 'username'"), value, state | |
493 | value, state) |
|
510 | ) | |
494 |
|
511 | |||
495 | return value |
|
512 | return value | |
496 |
|
513 | |||
|
514 | ||||
497 | #============================================================================== |
|
515 | #============================================================================== | |
498 | # FORMS |
|
516 | # FORMS | |
499 | #============================================================================== |
|
517 | #============================================================================== | |
@@ -501,22 +519,22 b' class LoginForm(formencode.Schema):' | |||||
501 | allow_extra_fields = True |
|
519 | allow_extra_fields = True | |
502 | filter_extra_fields = True |
|
520 | filter_extra_fields = True | |
503 | username = UnicodeString( |
|
521 | username = UnicodeString( | |
504 |
|
|
522 | strip=True, | |
505 | min=1, |
|
523 | min=1, | |
506 |
|
|
524 | not_empty=True, | |
507 |
|
|
525 | messages={ | |
508 |
|
|
526 | 'empty': _('Please enter a login'), | |
509 |
|
|
527 | 'tooShort': _('Enter a value %(min)i characters long or more')} | |
510 | ) |
|
528 | ) | |
511 |
|
529 | |||
512 | password = UnicodeString( |
|
530 | password = UnicodeString( | |
513 |
|
|
531 | strip=True, | |
514 | min=3, |
|
532 | min=3, | |
515 |
|
|
533 | not_empty=True, | |
516 |
|
|
534 | messages={ | |
517 |
|
|
535 | 'empty': _('Please enter a password'), | |
518 |
|
|
536 | 'tooShort': _('Enter %(min)i characters or more')} | |
519 | ) |
|
537 | ) | |
520 |
|
538 | |||
521 | remember = StringBoolean(if_missing=False) |
|
539 | remember = StringBoolean(if_missing=False) | |
522 |
|
540 | |||
@@ -531,15 +549,17 b' def UserForm(edit=False, old_data={}):' | |||||
531 | ValidUsername(edit, old_data)) |
|
549 | ValidUsername(edit, old_data)) | |
532 | if edit: |
|
550 | if edit: | |
533 | new_password = All(UnicodeString(strip=True, min=6, not_empty=False)) |
|
551 | new_password = All(UnicodeString(strip=True, min=6, not_empty=False)) | |
534 |
password_confirmation = All(UnicodeString(strip=True, min=6, |
|
552 | password_confirmation = All(UnicodeString(strip=True, min=6, | |
|
553 | not_empty=False)) | |||
535 | admin = StringBoolean(if_missing=False) |
|
554 | admin = StringBoolean(if_missing=False) | |
536 | else: |
|
555 | else: | |
537 | password = All(UnicodeString(strip=True, min=6, not_empty=True)) |
|
556 | password = All(UnicodeString(strip=True, min=6, not_empty=True)) | |
538 |
password_confirmation = All(UnicodeString(strip=True, min=6, |
|
557 | password_confirmation = All(UnicodeString(strip=True, min=6, | |
|
558 | not_empty=False)) | |||
539 |
|
559 | |||
540 | active = StringBoolean(if_missing=False) |
|
560 | active = StringBoolean(if_missing=False) | |
541 |
name = UnicodeString(strip=True, min=1, not_empty= |
|
561 | name = UnicodeString(strip=True, min=1, not_empty=False) | |
542 |
lastname = UnicodeString(strip=True, min=1, not_empty= |
|
562 | lastname = UnicodeString(strip=True, min=1, not_empty=False) | |
543 | email = All(Email(not_empty=True), UniqSystemEmail(old_data)) |
|
563 | email = All(Email(not_empty=True), UniqSystemEmail(old_data)) | |
544 |
|
564 | |||
545 | chained_validators = [ValidPasswordsMatch, ValidPassword] |
|
565 | chained_validators = [ValidPasswordsMatch, ValidPassword] | |
@@ -592,14 +612,15 b' def RegisterForm(edit=False, old_data={}' | |||||
592 | password = All(UnicodeString(strip=True, min=6, not_empty=True)) |
|
612 | password = All(UnicodeString(strip=True, min=6, not_empty=True)) | |
593 | password_confirmation = All(UnicodeString(strip=True, min=6, not_empty=True)) |
|
613 | password_confirmation = All(UnicodeString(strip=True, min=6, not_empty=True)) | |
594 | active = StringBoolean(if_missing=False) |
|
614 | active = StringBoolean(if_missing=False) | |
595 |
name = UnicodeString(strip=True, min=1, not_empty= |
|
615 | name = UnicodeString(strip=True, min=1, not_empty=False) | |
596 |
lastname = UnicodeString(strip=True, min=1, not_empty= |
|
616 | lastname = UnicodeString(strip=True, min=1, not_empty=False) | |
597 | email = All(Email(not_empty=True), UniqSystemEmail(old_data)) |
|
617 | email = All(Email(not_empty=True), UniqSystemEmail(old_data)) | |
598 |
|
618 | |||
599 | chained_validators = [ValidPasswordsMatch, ValidPassword] |
|
619 | chained_validators = [ValidPasswordsMatch, ValidPassword] | |
600 |
|
620 | |||
601 | return _RegisterForm |
|
621 | return _RegisterForm | |
602 |
|
622 | |||
|
623 | ||||
603 | def PasswordResetForm(): |
|
624 | def PasswordResetForm(): | |
604 | class _PasswordResetForm(formencode.Schema): |
|
625 | class _PasswordResetForm(formencode.Schema): | |
605 | allow_extra_fields = True |
|
626 | allow_extra_fields = True | |
@@ -607,6 +628,7 b' def PasswordResetForm():' | |||||
607 | email = All(ValidSystemEmail(), Email(not_empty=True)) |
|
628 | email = All(ValidSystemEmail(), Email(not_empty=True)) | |
608 | return _PasswordResetForm |
|
629 | return _PasswordResetForm | |
609 |
|
630 | |||
|
631 | ||||
610 | def RepoForm(edit=False, old_data={}, supported_backends=BACKENDS.keys(), |
|
632 | def RepoForm(edit=False, old_data={}, supported_backends=BACKENDS.keys(), | |
611 | repo_groups=[]): |
|
633 | repo_groups=[]): | |
612 | class _RepoForm(formencode.Schema): |
|
634 | class _RepoForm(formencode.Schema): | |
@@ -630,6 +652,7 b' def RepoForm(edit=False, old_data={}, su' | |||||
630 | chained_validators = [ValidRepoName(edit, old_data), ValidPerms] |
|
652 | chained_validators = [ValidRepoName(edit, old_data), ValidPerms] | |
631 | return _RepoForm |
|
653 | return _RepoForm | |
632 |
|
654 | |||
|
655 | ||||
633 | def RepoForkForm(edit=False, old_data={}, supported_backends=BACKENDS.keys(), |
|
656 | def RepoForkForm(edit=False, old_data={}, supported_backends=BACKENDS.keys(), | |
634 | repo_groups=[]): |
|
657 | repo_groups=[]): | |
635 | class _RepoForkForm(formencode.Schema): |
|
658 | class _RepoForkForm(formencode.Schema): | |
@@ -648,6 +671,7 b' def RepoForkForm(edit=False, old_data={}' | |||||
648 |
|
671 | |||
649 | return _RepoForkForm |
|
672 | return _RepoForkForm | |
650 |
|
673 | |||
|
674 | ||||
651 | def RepoSettingsForm(edit=False, old_data={}, supported_backends=BACKENDS.keys(), |
|
675 | def RepoSettingsForm(edit=False, old_data={}, supported_backends=BACKENDS.keys(), | |
652 | repo_groups=[]): |
|
676 | repo_groups=[]): | |
653 | class _RepoForm(formencode.Schema): |
|
677 | class _RepoForm(formencode.Schema): | |
@@ -674,6 +698,7 b' def ApplicationSettingsForm():' | |||||
674 |
|
698 | |||
675 | return _ApplicationSettingsForm |
|
699 | return _ApplicationSettingsForm | |
676 |
|
700 | |||
|
701 | ||||
677 | def ApplicationUiSettingsForm(): |
|
702 | def ApplicationUiSettingsForm(): | |
678 | class _ApplicationUiSettingsForm(formencode.Schema): |
|
703 | class _ApplicationUiSettingsForm(formencode.Schema): | |
679 | allow_extra_fields = True |
|
704 | allow_extra_fields = True | |
@@ -687,6 +712,7 b' def ApplicationUiSettingsForm():' | |||||
687 |
|
712 | |||
688 | return _ApplicationUiSettingsForm |
|
713 | return _ApplicationUiSettingsForm | |
689 |
|
714 | |||
|
715 | ||||
690 | def DefaultPermissionsForm(perms_choices, register_choices, create_choices): |
|
716 | def DefaultPermissionsForm(perms_choices, register_choices, create_choices): | |
691 | class _DefaultPermissionsForm(formencode.Schema): |
|
717 | class _DefaultPermissionsForm(formencode.Schema): | |
692 | allow_extra_fields = True |
|
718 | allow_extra_fields = True |
@@ -92,7 +92,6 b' class UserModel(BaseModel):' | |||||
92 | log.error(traceback.format_exc()) |
|
92 | log.error(traceback.format_exc()) | |
93 | raise |
|
93 | raise | |
94 |
|
94 | |||
95 |
|
||||
96 | def create_or_update(self, username, password, email, name, lastname, |
|
95 | def create_or_update(self, username, password, email, name, lastname, | |
97 | active=True, admin=False, ldap_dn=None): |
|
96 | active=True, admin=False, ldap_dn=None): | |
98 | """ |
|
97 | """ | |
@@ -136,7 +135,6 b' class UserModel(BaseModel):' | |||||
136 | log.error(traceback.format_exc()) |
|
135 | log.error(traceback.format_exc()) | |
137 | raise |
|
136 | raise | |
138 |
|
137 | |||
139 |
|
||||
140 | def create_for_container_auth(self, username, attrs): |
|
138 | def create_for_container_auth(self, username, attrs): | |
141 | """ |
|
139 | """ | |
142 | Creates the given user if it's not already in the database |
|
140 | Creates the given user if it's not already in the database | |
@@ -231,7 +229,7 b' class UserModel(BaseModel):' | |||||
231 | body = body % (new_user.username, new_user.full_name, |
|
229 | body = body % (new_user.username, new_user.full_name, | |
232 | new_user.email) |
|
230 | new_user.email) | |
233 | edit_url = url('edit_user', id=new_user.user_id, qualified=True) |
|
231 | edit_url = url('edit_user', id=new_user.user_id, qualified=True) | |
234 | kw = {'registered_user_url':edit_url} |
|
232 | kw = {'registered_user_url': edit_url} | |
235 | NotificationModel().create(created_by=new_user, subject=subject, |
|
233 | NotificationModel().create(created_by=new_user, subject=subject, | |
236 | body=body, recipients=None, |
|
234 | body=body, recipients=None, | |
237 | type_=Notification.TYPE_REGISTRATION, |
|
235 | type_=Notification.TYPE_REGISTRATION, | |
@@ -493,7 +491,6 b' class UserModel(BaseModel):' | |||||
493 | new.permission = perm |
|
491 | new.permission = perm | |
494 | self.sa.add(new) |
|
492 | self.sa.add(new) | |
495 |
|
493 | |||
496 |
|
||||
497 | def revoke_perm(self, user, perm): |
|
494 | def revoke_perm(self, user, perm): | |
498 | if not isinstance(perm, Permission): |
|
495 | if not isinstance(perm, Permission): | |
499 | raise Exception('perm needs to be an instance of Permission class ' |
|
496 | raise Exception('perm needs to be an instance of Permission class ' |
@@ -86,7 +86,7 b'' | |||||
86 | <label for="active">${_('Active')}:</label> |
|
86 | <label for="active">${_('Active')}:</label> | |
87 | </div> |
|
87 | </div> | |
88 | <div class="checkboxes"> |
|
88 | <div class="checkboxes"> | |
89 | ${h.checkbox('active',value=True)} |
|
89 | ${h.checkbox('active',value=True,checked='checked')} | |
90 | </div> |
|
90 | </div> | |
91 | </div> |
|
91 | </div> | |
92 |
|
92 |
@@ -112,7 +112,7 b'' | |||||
112 | ${h.end_form()} |
|
112 | ${h.end_form()} | |
113 | %else: |
|
113 | %else: | |
114 | <div class="links_left"> |
|
114 | <div class="links_left"> | |
115 | <div class="full_name">${c.rhodecode_user.full_name}</div> |
|
115 | <div class="full_name">${c.rhodecode_user.full_name_or_username}</div> | |
116 | <div class="email">${c.rhodecode_user.email}</div> |
|
116 | <div class="email">${c.rhodecode_user.email}</div> | |
117 | <div class="big_gravatar"><img alt="gravatar" src="${h.gravatar_url(c.rhodecode_user.email,48)}" /></div> |
|
117 | <div class="big_gravatar"><img alt="gravatar" src="${h.gravatar_url(c.rhodecode_user.email,48)}" /></div> | |
118 | </div> |
|
118 | </div> |
General Comments 0
You need to be logged in to leave comments.
Login now