##// END OF EJS Templates
fixed #72 show warning on removal when user still is owner of existing repositories...
marcink -
r713:1bb0fcde beta
parent child Browse files
Show More
@@ -1,166 +1,167 b''
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3 # users controller for pylons
4 4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5 5 #
6 6 # This program is free software; you can redistribute it and/or
7 7 # modify it under the terms of the GNU General Public License
8 8 # as published by the Free Software Foundation; version 2
9 9 # of the License or (at your opinion) any later version of the license.
10 10 #
11 11 # This program is distributed in the hope that it will be useful,
12 12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 14 # GNU General Public License for more details.
15 15 #
16 16 # You should have received a copy of the GNU General Public License
17 17 # along with this program; if not, write to the Free Software
18 18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 19 # MA 02110-1301, USA.
20 20 """
21 21 Created on April 4, 2010
22 22 users controller for pylons
23 23 @author: marcink
24 24 """
25 25
26 26 from formencode import htmlfill
27 27 from pylons import request, session, tmpl_context as c, url
28 28 from pylons.controllers.util import abort, redirect
29 29 from pylons.i18n.translation import _
30 from rhodecode.lib.exceptions import *
30 31 from rhodecode.lib import helpers as h
31 32 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
32 33 from rhodecode.lib.base import BaseController, render
33 from rhodecode.model.db import User, UserLog
34 from rhodecode.model.db import User
34 35 from rhodecode.model.forms import UserForm
35 from rhodecode.model.user import UserModel, DefaultUserException
36 from rhodecode.model.user import UserModel
36 37 import formencode
37 38 import logging
38 39 import traceback
39 40
40 41 log = logging.getLogger(__name__)
41 42
42 43 class UsersController(BaseController):
43 44 """REST Controller styled on the Atom Publishing Protocol"""
44 45 # To properly map this controller, ensure your config/routing.py
45 46 # file has a resource setup:
46 47 # map.resource('user', 'users')
47 48
48 49 @LoginRequired()
49 50 @HasPermissionAllDecorator('hg.admin')
50 51 def __before__(self):
51 52 c.admin_user = session.get('admin_user')
52 53 c.admin_username = session.get('admin_username')
53 54 super(UsersController, self).__before__()
54 55
55 56
56 57 def index(self, format='html'):
57 58 """GET /users: All items in the collection"""
58 59 # url('users')
59 60
60 61 c.users_list = self.sa.query(User).all()
61 62 return render('admin/users/users.html')
62 63
63 64 def create(self):
64 65 """POST /users: Create a new item"""
65 66 # url('users')
66 67
67 68 user_model = UserModel()
68 69 login_form = UserForm()()
69 70 try:
70 71 form_result = login_form.to_python(dict(request.POST))
71 72 user_model.create(form_result)
72 73 h.flash(_('created user %s') % form_result['username'],
73 74 category='success')
74 75 #action_logger(self.rhodecode_user, 'new_user', '', '', self.sa)
75 76 except formencode.Invalid, errors:
76 77 return htmlfill.render(
77 78 render('admin/users/user_add.html'),
78 79 defaults=errors.value,
79 80 errors=errors.error_dict or {},
80 81 prefix_error=False,
81 82 encoding="UTF-8")
82 83 except Exception:
83 84 log.error(traceback.format_exc())
84 85 h.flash(_('error occured during creation of user %s') \
85 86 % request.POST.get('username'), category='error')
86 87 return redirect(url('users'))
87 88
88 89 def new(self, format='html'):
89 90 """GET /users/new: Form to create a new item"""
90 91 # url('new_user')
91 92 return render('admin/users/user_add.html')
92 93
93 94 def update(self, id):
94 95 """PUT /users/id: Update an existing item"""
95 96 # Forms posted to this method should contain a hidden field:
96 97 # <input type="hidden" name="_method" value="PUT" />
97 98 # Or using helpers:
98 99 # h.form(url('user', id=ID),
99 100 # method='put')
100 101 # url('user', id=ID)
101 102 user_model = UserModel()
102 103 c.user = user_model.get(id)
103 104
104 105 _form = UserForm(edit=True, old_data={'user_id':id,
105 106 'email':c.user.email})()
106 107 form_result = {}
107 108 try:
108 109 form_result = _form.to_python(dict(request.POST))
109 110 user_model.update(id, form_result)
110 111 h.flash(_('User updated succesfully'), category='success')
111 112
112 113 except formencode.Invalid, errors:
113 114 return htmlfill.render(
114 115 render('admin/users/user_edit.html'),
115 116 defaults=errors.value,
116 117 errors=errors.error_dict or {},
117 118 prefix_error=False,
118 119 encoding="UTF-8")
119 120 except Exception:
120 121 log.error(traceback.format_exc())
121 122 h.flash(_('error occured during update of user %s') \
122 123 % form_result.get('username'), category='error')
123 124
124 125 return redirect(url('users'))
125 126
126 127 def delete(self, id):
127 128 """DELETE /users/id: Delete an existing item"""
128 129 # Forms posted to this method should contain a hidden field:
129 130 # <input type="hidden" name="_method" value="DELETE" />
130 131 # Or using helpers:
131 132 # h.form(url('user', id=ID),
132 133 # method='delete')
133 134 # url('user', id=ID)
134 135 user_model = UserModel()
135 136 try:
136 137 user_model.delete(id)
137 138 h.flash(_('sucessfully deleted user'), category='success')
138 except DefaultUserException, e:
139 except (UserOwnsReposException, DefaultUserException), e:
139 140 h.flash(str(e), category='warning')
140 141 except Exception:
141 142 h.flash(_('An error occured during deletion of user'),
142 143 category='error')
143 144 return redirect(url('users'))
144 145
145 146 def show(self, id, format='html'):
146 147 """GET /users/id: Show a specific item"""
147 148 # url('user', id=ID)
148 149
149 150
150 151 def edit(self, id, format='html'):
151 152 """GET /users/id/edit: Form to edit an existing item"""
152 153 # url('edit_user', id=ID)
153 154 c.user = self.sa.query(User).get(id)
154 155 if not c.user:
155 156 return redirect(url('users'))
156 157 if c.user.username == 'default':
157 158 h.flash(_("You can't edit this user"), category='warning')
158 159 return redirect(url('users'))
159 160
160 161 defaults = c.user.__dict__
161 162 return htmlfill.render(
162 163 render('admin/users/user_edit.html'),
163 164 defaults=defaults,
164 165 encoding="UTF-8",
165 166 force_defaults=False
166 167 )
@@ -1,525 +1,526 b''
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3 # authentication and permission libraries
4 4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5 5 #
6 6 # This program is free software; you can redistribute it and/or
7 7 # modify it under the terms of the GNU General Public License
8 8 # as published by the Free Software Foundation; version 2
9 9 # of the License or (at your opinion) any later version of the license.
10 10 #
11 11 # This program is distributed in the hope that it will be useful,
12 12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 14 # GNU General Public License for more details.
15 15 #
16 16 # You should have received a copy of the GNU General Public License
17 17 # along with this program; if not, write to the Free Software
18 18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 19 # MA 02110-1301, USA.
20 20 """
21 21 Created on April 4, 2010
22 22
23 23 @author: marcink
24 24 """
25 25 from pylons import config, session, url, request
26 26 from pylons.controllers.util import abort, redirect
27 from rhodecode.lib.exceptions import *
27 28 from rhodecode.lib.utils import get_repo_slug
28 from rhodecode.lib.auth_ldap import AuthLdap, UsernameError, PasswordError
29 from rhodecode.lib.auth_ldap import AuthLdap
29 30 from rhodecode.model import meta
30 31 from rhodecode.model.user import UserModel
31 32 from rhodecode.model.caching_query import FromCache
32 33 from rhodecode.model.db import User, RepoToPerm, Repository, Permission, \
33 34 UserToPerm
34 35 import bcrypt
35 36 from decorator import decorator
36 37 import logging
37 38 import random
38 39 import traceback
39 40
40 41 log = logging.getLogger(__name__)
41 42
42 43 class PasswordGenerator(object):
43 44 """This is a simple class for generating password from
44 45 different sets of characters
45 46 usage:
46 47 passwd_gen = PasswordGenerator()
47 48 #print 8-letter password containing only big and small letters of alphabet
48 49 print passwd_gen.gen_password(8, passwd_gen.ALPHABETS_BIG_SMALL)
49 50 """
50 51 ALPHABETS_NUM = r'''1234567890'''#[0]
51 52 ALPHABETS_SMALL = r'''qwertyuiopasdfghjklzxcvbnm'''#[1]
52 53 ALPHABETS_BIG = r'''QWERTYUIOPASDFGHJKLZXCVBNM'''#[2]
53 54 ALPHABETS_SPECIAL = r'''`-=[]\;',./~!@#$%^&*()_+{}|:"<>?''' #[3]
54 55 ALPHABETS_FULL = ALPHABETS_BIG + ALPHABETS_SMALL + ALPHABETS_NUM + ALPHABETS_SPECIAL#[4]
55 56 ALPHABETS_ALPHANUM = ALPHABETS_BIG + ALPHABETS_SMALL + ALPHABETS_NUM#[5]
56 57 ALPHABETS_BIG_SMALL = ALPHABETS_BIG + ALPHABETS_SMALL
57 58 ALPHABETS_ALPHANUM_BIG = ALPHABETS_BIG + ALPHABETS_NUM#[6]
58 59 ALPHABETS_ALPHANUM_SMALL = ALPHABETS_SMALL + ALPHABETS_NUM#[7]
59 60
60 61 def __init__(self, passwd=''):
61 62 self.passwd = passwd
62 63
63 64 def gen_password(self, len, type):
64 65 self.passwd = ''.join([random.choice(type) for _ in xrange(len)])
65 66 return self.passwd
66 67
67 68
68 69 def get_crypt_password(password):
69 70 """Cryptographic function used for password hashing based on sha1
70 71 :param password: password to hash
71 72 """
72 73 return bcrypt.hashpw(password, bcrypt.gensalt(10))
73 74
74 75 def check_password(password, hashed):
75 76 return bcrypt.hashpw(password, hashed) == hashed
76 77
77 78 def authfunc(environ, username, password):
78 79 """
79 80 Authentication function used in Mercurial/Git/ and access control,
80 81 firstly checks for db authentication then if ldap is enabled for ldap
81 82 authentication, also creates ldap user if not in database
82 83
83 84 :param environ: needed only for using in Basic auth, can be None
84 85 :param username: username
85 86 :param password: password
86 87 """
87 88 user_model = UserModel()
88 89 user = user_model.get_by_username(username, cache=False)
89 90
90 91 if user is not None and user.is_ldap is False:
91 92 if user.active:
92 93
93 94 if user.username == 'default' and user.active:
94 95 log.info('user %s authenticated correctly', username)
95 96 return True
96 97
97 98 elif user.username == username and check_password(password, user.password):
98 99 log.info('user %s authenticated correctly', username)
99 100 return True
100 101 else:
101 102 log.error('user %s is disabled', username)
102 103
103 104
104 105 else:
105 106 from rhodecode.model.settings import SettingsModel
106 107 ldap_settings = SettingsModel().get_ldap_settings()
107 108
108 109 #======================================================================
109 110 # FALLBACK TO LDAP AUTH IN ENABLE
110 111 #======================================================================
111 112 if ldap_settings.get('ldap_active', False):
112 113 kwargs = {
113 114 'server':ldap_settings.get('ldap_host', ''),
114 115 'base_dn':ldap_settings.get('ldap_base_dn', ''),
115 116 'port':ldap_settings.get('ldap_port'),
116 117 'bind_dn':ldap_settings.get('ldap_dn_user'),
117 118 'bind_pass':ldap_settings.get('ldap_dn_pass'),
118 119 'use_ldaps':ldap_settings.get('ldap_ldaps'),
119 120 'ldap_version':3,
120 121 }
121 122 log.debug('Checking for ldap authentication')
122 123 try:
123 124 aldap = AuthLdap(**kwargs)
124 125 res = aldap.authenticate_ldap(username, password)
125 126
126 127 authenticated = res[1]['uid'][0] == username
127 128
128 129 if authenticated and user_model.create_ldap(username, password):
129 130 log.info('created new ldap user')
130 131
131 132 return authenticated
132 except (UsernameError, PasswordError):
133 except (LdapUsernameError, LdapPasswordError):
133 134 return False
134 135 except:
135 136 log.error(traceback.format_exc())
136 137 return False
137 138 return False
138 139
139 140 class AuthUser(object):
140 141 """
141 142 A simple object that handles a mercurial username for authentication
142 143 """
143 144 def __init__(self):
144 145 self.username = 'None'
145 146 self.name = ''
146 147 self.lastname = ''
147 148 self.email = ''
148 149 self.user_id = None
149 150 self.is_authenticated = False
150 151 self.is_admin = False
151 152 self.permissions = {}
152 153
153 154 def __repr__(self):
154 155 return "<AuthUser('id:%s:%s')>" % (self.user_id, self.username)
155 156
156 157 def set_available_permissions(config):
157 158 """
158 159 This function will propagate pylons globals with all available defined
159 160 permission given in db. We don't wannt to check each time from db for new
160 161 permissions since adding a new permission also requires application restart
161 162 ie. to decorate new views with the newly created permission
162 163 :param config:
163 164 """
164 165 log.info('getting information about all available permissions')
165 166 try:
166 167 sa = meta.Session()
167 168 all_perms = sa.query(Permission).all()
168 169 except:
169 170 pass
170 171 finally:
171 172 meta.Session.remove()
172 173
173 174 config['available_permissions'] = [x.permission_name for x in all_perms]
174 175
175 176 def set_base_path(config):
176 177 config['base_path'] = config['pylons.app_globals'].base_path
177 178
178 179
179 180 def fill_perms(user):
180 181 """
181 182 Fills user permission attribute with permissions taken from database
182 183 :param user:
183 184 """
184 185
185 186 sa = meta.Session()
186 187 user.permissions['repositories'] = {}
187 188 user.permissions['global'] = set()
188 189
189 190 #===========================================================================
190 191 # fetch default permissions
191 192 #===========================================================================
192 193 default_user = UserModel().get_by_username('default', cache=True)
193 194
194 195 default_perms = sa.query(RepoToPerm, Repository, Permission)\
195 196 .join((Repository, RepoToPerm.repository_id == Repository.repo_id))\
196 197 .join((Permission, RepoToPerm.permission_id == Permission.permission_id))\
197 198 .filter(RepoToPerm.user == default_user).all()
198 199
199 200 if user.is_admin:
200 201 #=======================================================================
201 202 # #admin have all default rights set to admin
202 203 #=======================================================================
203 204 user.permissions['global'].add('hg.admin')
204 205
205 206 for perm in default_perms:
206 207 p = 'repository.admin'
207 208 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
208 209
209 210 else:
210 211 #=======================================================================
211 212 # set default permissions
212 213 #=======================================================================
213 214
214 215 #default global
215 216 default_global_perms = sa.query(UserToPerm)\
216 217 .filter(UserToPerm.user == sa.query(User).filter(User.username ==
217 218 'default').one())
218 219
219 220 for perm in default_global_perms:
220 221 user.permissions['global'].add(perm.permission.permission_name)
221 222
222 223 #default repositories
223 224 for perm in default_perms:
224 225 if perm.Repository.private and not perm.Repository.user_id == user.user_id:
225 226 #disable defaults for private repos,
226 227 p = 'repository.none'
227 228 elif perm.Repository.user_id == user.user_id:
228 229 #set admin if owner
229 230 p = 'repository.admin'
230 231 else:
231 232 p = perm.Permission.permission_name
232 233
233 234 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
234 235
235 236 #=======================================================================
236 237 # #overwrite default with user permissions if any
237 238 #=======================================================================
238 239 user_perms = sa.query(RepoToPerm, Permission, Repository)\
239 240 .join((Repository, RepoToPerm.repository_id == Repository.repo_id))\
240 241 .join((Permission, RepoToPerm.permission_id == Permission.permission_id))\
241 242 .filter(RepoToPerm.user_id == user.user_id).all()
242 243
243 244 for perm in user_perms:
244 245 if perm.Repository.user_id == user.user_id:#set admin if owner
245 246 p = 'repository.admin'
246 247 else:
247 248 p = perm.Permission.permission_name
248 249 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
249 250 meta.Session.remove()
250 251 return user
251 252
252 253 def get_user(session):
253 254 """
254 255 Gets user from session, and wraps permissions into user
255 256 :param session:
256 257 """
257 258 user = session.get('rhodecode_user', AuthUser())
258 259 #if the user is not logged in we check for anonymous access
259 260 #if user is logged and it's a default user check if we still have anonymous
260 261 #access enabled
261 262 if user.user_id is None or user.username == 'default':
262 263 anonymous_user = UserModel().get_by_username('default', cache=True)
263 264 if anonymous_user.active is True:
264 265 #then we set this user is logged in
265 266 user.is_authenticated = True
266 267 user.user_id = anonymous_user.user_id
267 268 else:
268 269 user.is_authenticated = False
269 270
270 271 if user.is_authenticated:
271 272 user = UserModel().fill_data(user)
272 273
273 274 user = fill_perms(user)
274 275 session['rhodecode_user'] = user
275 276 session.save()
276 277 return user
277 278
278 279 #===============================================================================
279 280 # CHECK DECORATORS
280 281 #===============================================================================
281 282 class LoginRequired(object):
282 283 """Must be logged in to execute this function else redirect to login page"""
283 284
284 285 def __call__(self, func):
285 286 return decorator(self.__wrapper, func)
286 287
287 288 def __wrapper(self, func, *fargs, **fkwargs):
288 289 user = session.get('rhodecode_user', AuthUser())
289 290 log.debug('Checking login required for user:%s', user.username)
290 291 if user.is_authenticated:
291 292 log.debug('user %s is authenticated', user.username)
292 293 return func(*fargs, **fkwargs)
293 294 else:
294 295 log.warn('user %s not authenticated', user.username)
295 296
296 297 p = ''
297 298 if request.environ.get('SCRIPT_NAME') != '/':
298 299 p += request.environ.get('SCRIPT_NAME')
299 300
300 301 p += request.environ.get('PATH_INFO')
301 302 if request.environ.get('QUERY_STRING'):
302 303 p += '?' + request.environ.get('QUERY_STRING')
303 304
304 305 log.debug('redirecting to login page with %s', p)
305 306 return redirect(url('login_home', came_from=p))
306 307
307 308 class PermsDecorator(object):
308 309 """Base class for decorators"""
309 310
310 311 def __init__(self, *required_perms):
311 312 available_perms = config['available_permissions']
312 313 for perm in required_perms:
313 314 if perm not in available_perms:
314 315 raise Exception("'%s' permission is not defined" % perm)
315 316 self.required_perms = set(required_perms)
316 317 self.user_perms = None
317 318
318 319 def __call__(self, func):
319 320 return decorator(self.__wrapper, func)
320 321
321 322
322 323 def __wrapper(self, func, *fargs, **fkwargs):
323 324 # _wrapper.__name__ = func.__name__
324 325 # _wrapper.__dict__.update(func.__dict__)
325 326 # _wrapper.__doc__ = func.__doc__
326 327 self.user = session.get('rhodecode_user', AuthUser())
327 328 self.user_perms = self.user.permissions
328 329 log.debug('checking %s permissions %s for %s %s',
329 330 self.__class__.__name__, self.required_perms, func.__name__,
330 331 self.user)
331 332
332 333 if self.check_permissions():
333 334 log.debug('Permission granted for %s %s', func.__name__, self.user)
334 335
335 336 return func(*fargs, **fkwargs)
336 337
337 338 else:
338 339 log.warning('Permission denied for %s %s', func.__name__, self.user)
339 340 #redirect with forbidden ret code
340 341 return abort(403)
341 342
342 343
343 344
344 345 def check_permissions(self):
345 346 """Dummy function for overriding"""
346 347 raise Exception('You have to write this function in child class')
347 348
348 349 class HasPermissionAllDecorator(PermsDecorator):
349 350 """Checks for access permission for all given predicates. All of them
350 351 have to be meet in order to fulfill the request
351 352 """
352 353
353 354 def check_permissions(self):
354 355 if self.required_perms.issubset(self.user_perms.get('global')):
355 356 return True
356 357 return False
357 358
358 359
359 360 class HasPermissionAnyDecorator(PermsDecorator):
360 361 """Checks for access permission for any of given predicates. In order to
361 362 fulfill the request any of predicates must be meet
362 363 """
363 364
364 365 def check_permissions(self):
365 366 if self.required_perms.intersection(self.user_perms.get('global')):
366 367 return True
367 368 return False
368 369
369 370 class HasRepoPermissionAllDecorator(PermsDecorator):
370 371 """Checks for access permission for all given predicates for specific
371 372 repository. All of them have to be meet in order to fulfill the request
372 373 """
373 374
374 375 def check_permissions(self):
375 376 repo_name = get_repo_slug(request)
376 377 try:
377 378 user_perms = set([self.user_perms['repositories'][repo_name]])
378 379 except KeyError:
379 380 return False
380 381 if self.required_perms.issubset(user_perms):
381 382 return True
382 383 return False
383 384
384 385
385 386 class HasRepoPermissionAnyDecorator(PermsDecorator):
386 387 """Checks for access permission for any of given predicates for specific
387 388 repository. In order to fulfill the request any of predicates must be meet
388 389 """
389 390
390 391 def check_permissions(self):
391 392 repo_name = get_repo_slug(request)
392 393
393 394 try:
394 395 user_perms = set([self.user_perms['repositories'][repo_name]])
395 396 except KeyError:
396 397 return False
397 398 if self.required_perms.intersection(user_perms):
398 399 return True
399 400 return False
400 401 #===============================================================================
401 402 # CHECK FUNCTIONS
402 403 #===============================================================================
403 404
404 405 class PermsFunction(object):
405 406 """Base function for other check functions"""
406 407
407 408 def __init__(self, *perms):
408 409 available_perms = config['available_permissions']
409 410
410 411 for perm in perms:
411 412 if perm not in available_perms:
412 413 raise Exception("'%s' permission in not defined" % perm)
413 414 self.required_perms = set(perms)
414 415 self.user_perms = None
415 416 self.granted_for = ''
416 417 self.repo_name = None
417 418
418 419 def __call__(self, check_Location=''):
419 420 user = session.get('rhodecode_user', False)
420 421 if not user:
421 422 return False
422 423 self.user_perms = user.permissions
423 424 self.granted_for = user.username
424 425 log.debug('checking %s %s %s', self.__class__.__name__,
425 426 self.required_perms, user)
426 427
427 428 if self.check_permissions():
428 429 log.debug('Permission granted for %s @ %s %s', self.granted_for,
429 430 check_Location, user)
430 431 return True
431 432
432 433 else:
433 434 log.warning('Permission denied for %s @ %s %s', self.granted_for,
434 435 check_Location, user)
435 436 return False
436 437
437 438 def check_permissions(self):
438 439 """Dummy function for overriding"""
439 440 raise Exception('You have to write this function in child class')
440 441
441 442 class HasPermissionAll(PermsFunction):
442 443 def check_permissions(self):
443 444 if self.required_perms.issubset(self.user_perms.get('global')):
444 445 return True
445 446 return False
446 447
447 448 class HasPermissionAny(PermsFunction):
448 449 def check_permissions(self):
449 450 if self.required_perms.intersection(self.user_perms.get('global')):
450 451 return True
451 452 return False
452 453
453 454 class HasRepoPermissionAll(PermsFunction):
454 455
455 456 def __call__(self, repo_name=None, check_Location=''):
456 457 self.repo_name = repo_name
457 458 return super(HasRepoPermissionAll, self).__call__(check_Location)
458 459
459 460 def check_permissions(self):
460 461 if not self.repo_name:
461 462 self.repo_name = get_repo_slug(request)
462 463
463 464 try:
464 465 self.user_perms = set([self.user_perms['repositories']\
465 466 [self.repo_name]])
466 467 except KeyError:
467 468 return False
468 469 self.granted_for = self.repo_name
469 470 if self.required_perms.issubset(self.user_perms):
470 471 return True
471 472 return False
472 473
473 474 class HasRepoPermissionAny(PermsFunction):
474 475
475 476 def __call__(self, repo_name=None, check_Location=''):
476 477 self.repo_name = repo_name
477 478 return super(HasRepoPermissionAny, self).__call__(check_Location)
478 479
479 480 def check_permissions(self):
480 481 if not self.repo_name:
481 482 self.repo_name = get_repo_slug(request)
482 483
483 484 try:
484 485 self.user_perms = set([self.user_perms['repositories']\
485 486 [self.repo_name]])
486 487 except KeyError:
487 488 return False
488 489 self.granted_for = self.repo_name
489 490 if self.required_perms.intersection(self.user_perms):
490 491 return True
491 492 return False
492 493
493 494 #===============================================================================
494 495 # SPECIAL VERSION TO HANDLE MIDDLEWARE AUTH
495 496 #===============================================================================
496 497
497 498 class HasPermissionAnyMiddleware(object):
498 499 def __init__(self, *perms):
499 500 self.required_perms = set(perms)
500 501
501 502 def __call__(self, user, repo_name):
502 503 usr = AuthUser()
503 504 usr.user_id = user.user_id
504 505 usr.username = user.username
505 506 usr.is_admin = user.admin
506 507
507 508 try:
508 509 self.user_perms = set([fill_perms(usr)\
509 510 .permissions['repositories'][repo_name]])
510 511 except:
511 512 self.user_perms = set()
512 513 self.granted_for = ''
513 514 self.username = user.username
514 515 self.repo_name = repo_name
515 516 return self.check_permissions()
516 517
517 518 def check_permissions(self):
518 519 log.debug('checking mercurial protocol '
519 520 'permissions for user:%s repository:%s',
520 521 self.username, self.repo_name)
521 522 if self.required_perms.intersection(self.user_perms):
522 523 log.debug('permission granted')
523 524 return True
524 525 log.debug('permission denied')
525 526 return False
@@ -1,93 +1,105 b''
1 #==============================================================================
2 # LDAP
3 #Name = Just a description for the auth modes page
4 #Host = DepartmentName.OrganizationName.local/ IP
5 #Port = 389 default for ldap
6 #LDAPS = no set True if You need to use ldaps
7 #Account = DepartmentName\UserName (or UserName@MyDomain depending on AD server)
8 #Password = <password>
9 #Base DN = DC=DepartmentName,DC=OrganizationName,DC=local
1 #!/usr/bin/env python
2 # encoding: utf-8
3 # ldap authentication lib
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5 #
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; version 2
9 # of the License or (at your opinion) any later version of the license.
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 # MA 02110-1301, USA.
20 """
21 Created on Nov 17, 2010
10 22
11 #==============================================================================
23 @author: marcink
24 """
12 25
13 from rhodecode.lib.exceptions import LdapImportError, UsernameError, \
14 PasswordError, ConnectionError
26 from rhodecode.lib.exceptions import *
15 27 import logging
16 28
17 29 log = logging.getLogger(__name__)
18 30
19 31 try:
20 32 import ldap
21 33 except ImportError:
22 34 pass
23 35
24 36 class AuthLdap(object):
25 37
26 38 def __init__(self, server, base_dn, port=389, bind_dn='', bind_pass='',
27 39 use_ldaps=False, ldap_version=3):
28 40 self.ldap_version = ldap_version
29 41 if use_ldaps:
30 42 port = port or 689
31 43 self.LDAP_USE_LDAPS = use_ldaps
32 44 self.LDAP_SERVER_ADDRESS = server
33 45 self.LDAP_SERVER_PORT = port
34 46
35 47 #USE FOR READ ONLY BIND TO LDAP SERVER
36 48 self.LDAP_BIND_DN = bind_dn
37 49 self.LDAP_BIND_PASS = bind_pass
38 50
39 51 ldap_server_type = 'ldap'
40 52 if self.LDAP_USE_LDAPS:ldap_server_type = ldap_server_type + 's'
41 53 self.LDAP_SERVER = "%s://%s:%s" % (ldap_server_type,
42 54 self.LDAP_SERVER_ADDRESS,
43 55 self.LDAP_SERVER_PORT)
44 56
45 57 self.BASE_DN = base_dn
46 58 self.AUTH_DN = "uid=%s,%s"
47 59
48 60 def authenticate_ldap(self, username, password):
49 61 """Authenticate a user via LDAP and return his/her LDAP properties.
50 62
51 63 Raises AuthenticationError if the credentials are rejected, or
52 64 EnvironmentError if the LDAP server can't be reached.
53 65
54 66 :param username: username
55 67 :param password: password
56 68 """
57 69
58 70 from rhodecode.lib.helpers import chop_at
59 71
60 72 uid = chop_at(username, "@%s" % self.LDAP_SERVER_ADDRESS)
61 73 dn = self.AUTH_DN % (uid, self.BASE_DN)
62 74 log.debug("Authenticating %r at %s", dn, self.LDAP_SERVER)
63 75 if "," in username:
64 raise UsernameError("invalid character in username: ,")
76 raise LdapUsernameError("invalid character in username: ,")
65 77 try:
66 78 ldap.set_option(ldap.OPT_X_TLS_CACERTFILE, '/etc/openldap/cacerts')
67 79 ldap.set_option(ldap.OPT_NETWORK_TIMEOUT, 10)
68 80 server = ldap.initialize(self.LDAP_SERVER)
69 81 if self.ldap_version == 2:
70 82 server.protocol = ldap.VERSION2
71 83 else:
72 84 server.protocol = ldap.VERSION3
73 85
74 86 if self.LDAP_BIND_DN and self.LDAP_BIND_PASS:
75 87 server.simple_bind_s(self.AUTH_DN % (self.LDAP_BIND_DN,
76 88 self.BASE_DN),
77 89 self.LDAP_BIND_PASS)
78 90
79 91 server.simple_bind_s(dn, password)
80 92 properties = server.search_s(dn, ldap.SCOPE_SUBTREE)
81 93 if not properties:
82 94 raise ldap.NO_SUCH_OBJECT()
83 95 except ldap.NO_SUCH_OBJECT, e:
84 96 log.debug("LDAP says no such user '%s' (%s)", uid, username)
85 raise UsernameError()
97 raise LdapUsernameError()
86 98 except ldap.INVALID_CREDENTIALS, e:
87 99 log.debug("LDAP rejected password for user '%s' (%s)", uid, username)
88 raise PasswordError()
100 raise LdapPasswordError()
89 101 except ldap.SERVER_DOWN, e:
90 raise ConnectionError("LDAP can't access authentication server")
102 raise LdapConnectionError("LDAP can't access authentication server")
91 103
92 104 return properties[0]
93 105
@@ -1,29 +1,32 b''
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3 # Custom Exceptions modules
4 4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5 5 #
6 6 # This program is free software; you can redistribute it and/or
7 7 # modify it under the terms of the GNU General Public License
8 8 # as published by the Free Software Foundation; version 2
9 9 # of the License or (at your opinion) any later version of the license.
10 10 #
11 11 # This program is distributed in the hope that it will be useful,
12 12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 14 # GNU General Public License for more details.
15 15 #
16 16 # You should have received a copy of the GNU General Public License
17 17 # along with this program; if not, write to the Free Software
18 18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 19 # MA 02110-1301, USA.
20 20 """
21 21 Created on Nov 17, 2010
22 22 Custom Exceptions modules
23 23 @author: marcink
24 24 """
25 25
26 class UsernameError(Exception):pass
27 class PasswordError(Exception):pass
28 class ConnectionError(Exception):pass
26 class LdapUsernameError(Exception):pass
27 class LdapPasswordError(Exception):pass
28 class LdapConnectionError(Exception):pass
29 29 class LdapImportError(Exception):pass
30
31 class DefaultUserException(Exception):pass
32 class UserOwnsReposException(Exception):pass
@@ -1,164 +1,166 b''
1 1 from rhodecode.model.meta import Base
2 2 from sqlalchemy import *
3 3 from sqlalchemy.orm import relation, backref
4 4 from sqlalchemy.orm.session import Session
5 5 from vcs.utils.lazy import LazyProperty
6 6 import logging
7 7 log = logging.getLogger(__name__)
8 8
9 9 class RhodeCodeSettings(Base):
10 10 __tablename__ = 'rhodecode_settings'
11 11 __table_args__ = (UniqueConstraint('app_settings_name'), {'useexisting':True})
12 12 app_settings_id = Column("app_settings_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
13 13 app_settings_name = Column("app_settings_name", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
14 14 app_settings_value = Column("app_settings_value", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
15 15
16 16 def __init__(self, k, v):
17 17 self.app_settings_name = k
18 18 self.app_settings_value = v
19 19
20 20 def __repr__(self):
21 21 return "<RhodeCodeSetting('%s:%s')>" % (self.app_settings_name,
22 22 self.app_settings_value)
23 23
24 24 class RhodeCodeUi(Base):
25 25 __tablename__ = 'rhodecode_ui'
26 26 __table_args__ = {'useexisting':True}
27 27 ui_id = Column("ui_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
28 28 ui_section = Column("ui_section", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
29 29 ui_key = Column("ui_key", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
30 30 ui_value = Column("ui_value", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
31 31 ui_active = Column("ui_active", BOOLEAN(), nullable=True, unique=None, default=True)
32 32
33 33
34 34 class User(Base):
35 35 __tablename__ = 'users'
36 36 __table_args__ = (UniqueConstraint('username'), UniqueConstraint('email'), {'useexisting':True})
37 37 user_id = Column("user_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
38 38 username = Column("username", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
39 39 password = Column("password", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
40 40 active = Column("active", BOOLEAN(), nullable=True, unique=None, default=None)
41 41 admin = Column("admin", BOOLEAN(), nullable=True, unique=None, default=False)
42 42 name = Column("name", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
43 43 lastname = Column("lastname", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
44 44 email = Column("email", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
45 45 last_login = Column("last_login", DATETIME(timezone=False), nullable=True, unique=None, default=None)
46 46 is_ldap = Column("is_ldap", BOOLEAN(), nullable=False, unique=None, default=False)
47 47
48 48 user_log = relation('UserLog', cascade='all')
49 49 user_perms = relation('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
50 50
51 repositories = relation('Repository')
52
51 53 @LazyProperty
52 54 def full_contact(self):
53 55 return '%s %s <%s>' % (self.name, self.lastname, self.email)
54 56
55 57 def __repr__(self):
56 58 return "<User('id:%s:%s')>" % (self.user_id, self.username)
57 59
58 60 def update_lastlogin(self):
59 61 """Update user lastlogin"""
60 62 import datetime
61 63
62 64 try:
63 65 session = Session.object_session(self)
64 66 self.last_login = datetime.datetime.now()
65 67 session.add(self)
66 68 session.commit()
67 69 log.debug('updated user %s lastlogin', self.username)
68 70 except Exception:
69 71 session.rollback()
70 72
71 73
72 74 class UserLog(Base):
73 75 __tablename__ = 'user_logs'
74 76 __table_args__ = {'useexisting':True}
75 77 user_log_id = Column("user_log_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
76 78 user_id = Column("user_id", INTEGER(), ForeignKey(u'users.user_id'), nullable=False, unique=None, default=None)
77 79 repository_id = Column("repository_id", INTEGER(length=None, convert_unicode=False, assert_unicode=None), ForeignKey(u'repositories.repo_id'), nullable=False, unique=None, default=None)
78 80 repository_name = Column("repository_name", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
79 81 user_ip = Column("user_ip", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
80 82 action = Column("action", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
81 83 action_date = Column("action_date", DATETIME(timezone=False), nullable=True, unique=None, default=None)
82 84
83 85 user = relation('User')
84 86 repository = relation('Repository')
85 87
86 88 class Repository(Base):
87 89 __tablename__ = 'repositories'
88 90 __table_args__ = (UniqueConstraint('repo_name'), {'useexisting':True},)
89 91 repo_id = Column("repo_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
90 92 repo_name = Column("repo_name", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
91 93 repo_type = Column("repo_type", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default=None)
92 94 user_id = Column("user_id", INTEGER(), ForeignKey(u'users.user_id'), nullable=False, unique=False, default=None)
93 95 private = Column("private", BOOLEAN(), nullable=True, unique=None, default=None)
94 96 description = Column("description", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
95 97 fork_id = Column("fork_id", INTEGER(), ForeignKey(u'repositories.repo_id'), nullable=True, unique=False, default=None)
96 98
97 99 user = relation('User')
98 100 fork = relation('Repository', remote_side=repo_id)
99 101 repo_to_perm = relation('RepoToPerm', cascade='all')
100 102 stats = relation('Statistics', cascade='all', uselist=False)
101 103
102 104 def __repr__(self):
103 105 return "<Repository('%s:%s')>" % (self.repo_id, self.repo_name)
104 106
105 107 class Permission(Base):
106 108 __tablename__ = 'permissions'
107 109 __table_args__ = {'useexisting':True}
108 110 permission_id = Column("permission_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
109 111 permission_name = Column("permission_name", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
110 112 permission_longname = Column("permission_longname", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
111 113
112 114 def __repr__(self):
113 115 return "<Permission('%s:%s')>" % (self.permission_id, self.permission_name)
114 116
115 117 class RepoToPerm(Base):
116 118 __tablename__ = 'repo_to_perm'
117 119 __table_args__ = (UniqueConstraint('user_id', 'repository_id'), {'useexisting':True})
118 120 repo_to_perm_id = Column("repo_to_perm_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
119 121 user_id = Column("user_id", INTEGER(), ForeignKey(u'users.user_id'), nullable=False, unique=None, default=None)
120 122 permission_id = Column("permission_id", INTEGER(), ForeignKey(u'permissions.permission_id'), nullable=False, unique=None, default=None)
121 123 repository_id = Column("repository_id", INTEGER(), ForeignKey(u'repositories.repo_id'), nullable=False, unique=None, default=None)
122 124
123 125 user = relation('User')
124 126 permission = relation('Permission')
125 127 repository = relation('Repository')
126 128
127 129 class UserToPerm(Base):
128 130 __tablename__ = 'user_to_perm'
129 131 __table_args__ = (UniqueConstraint('user_id', 'permission_id'), {'useexisting':True})
130 132 user_to_perm_id = Column("user_to_perm_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
131 133 user_id = Column("user_id", INTEGER(), ForeignKey(u'users.user_id'), nullable=False, unique=None, default=None)
132 134 permission_id = Column("permission_id", INTEGER(), ForeignKey(u'permissions.permission_id'), nullable=False, unique=None, default=None)
133 135
134 136 user = relation('User')
135 137 permission = relation('Permission')
136 138
137 139 class Statistics(Base):
138 140 __tablename__ = 'statistics'
139 141 __table_args__ = (UniqueConstraint('repository_id'), {'useexisting':True})
140 142 stat_id = Column("stat_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
141 143 repository_id = Column("repository_id", INTEGER(), ForeignKey(u'repositories.repo_id'), nullable=False, unique=True, default=None)
142 144 stat_on_revision = Column("stat_on_revision", INTEGER(), nullable=False)
143 145 commit_activity = Column("commit_activity", BLOB(), nullable=False)#JSON data
144 146 commit_activity_combined = Column("commit_activity_combined", BLOB(), nullable=False)#JSON data
145 147 languages = Column("languages", BLOB(), nullable=False)#JSON data
146 148
147 149 repository = relation('Repository', single_parent=True)
148 150
149 151 class CacheInvalidation(Base):
150 152 __tablename__ = 'cache_invalidation'
151 153 __table_args__ = (UniqueConstraint('cache_key'), {'useexisting':True})
152 154 cache_id = Column("cache_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
153 155 cache_key = Column("cache_key", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
154 156 cache_args = Column("cache_args", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
155 157 cache_active = Column("cache_active", BOOLEAN(), nullable=True, unique=None, default=False)
156 158
157 159
158 160 def __init__(self, cache_key, cache_args=''):
159 161 self.cache_key = cache_key
160 162 self.cache_args = cache_args
161 163 self.cache_active = False
162 164
163 165 def __repr__(self):
164 166 return "<CacheInvaidation('%s:%s')>" % (self.cache_id, self.cache_key)
@@ -1,207 +1,215 b''
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3 # Model for users
4 4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5 5 #
6 6 # This program is free software; you can redistribute it and/or
7 7 # modify it under the terms of the GNU General Public License
8 8 # as published by the Free Software Foundation; version 2
9 9 # of the License or (at your opinion) any later version of the license.
10 10 #
11 11 # This program is distributed in the hope that it will be useful,
12 12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 14 # GNU General Public License for more details.
15 15 #
16 16 # You should have received a copy of the GNU General Public License
17 17 # along with this program; if not, write to the Free Software
18 18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 19 # MA 02110-1301, USA.
20 20 """
21 21 Created on April 9, 2010
22 22 Model for users
23 23 :author: marcink
24 24 """
25 25
26 26 from pylons.i18n.translation import _
27 27 from rhodecode.model.caching_query import FromCache
28 28 from rhodecode.model.db import User
29 29 from rhodecode.model.meta import Session
30 from rhodecode.lib.exceptions import *
30 31 import logging
31 32 import traceback
32 33
33 34 log = logging.getLogger(__name__)
34 35
35 class DefaultUserException(Exception):pass
36
36 37
37 38 class UserModel(object):
38 39
39 40 def __init__(self):
40 41 self.sa = Session()
41 42
42 43 def get(self, user_id, cache=False):
43 44 user = self.sa.query(User)
44 45 if cache:
45 46 user = user.options(FromCache("sql_cache_short",
46 47 "get_user_%s" % user_id))
47 48 return user.get(user_id)
48 49
49 50
50 51 def get_by_username(self, username, cache=False):
51 52 user = self.sa.query(User)\
52 53 .filter(User.username == username)
53 54 if cache:
54 55 user = user.options(FromCache("sql_cache_short",
55 56 "get_user_%s" % username))
56 57 return user.scalar()
57 58
58 59 def create(self, form_data):
59 60 try:
60 61 new_user = User()
61 62 for k, v in form_data.items():
62 63 setattr(new_user, k, v)
63 64
64 65 self.sa.add(new_user)
65 66 self.sa.commit()
66 67 except:
67 68 log.error(traceback.format_exc())
68 69 self.sa.rollback()
69 70 raise
70 71
71 72 def create_ldap(self, username, password):
72 73 """
73 74 Checks if user is in database, if not creates this user marked
74 75 as ldap user
75 76 :param username:
76 77 :param password:
77 78 """
78 79
79 80 if self.get_by_username(username) is None:
80 81 try:
81 82 new_user = User()
82 83 new_user.username = username
83 84 new_user.password = password
84 85 new_user.email = '%s@ldap.server' % username
85 86 new_user.active = True
86 87 new_user.is_ldap = True
87 88 new_user.name = '%s@ldap' % username
88 89 new_user.lastname = ''
89 90
90 91
91 92 self.sa.add(new_user)
92 93 self.sa.commit()
93 94 return True
94 95 except:
95 96 log.error(traceback.format_exc())
96 97 self.sa.rollback()
97 98 raise
98 99
99 100 return False
100 101
101 102 def create_registration(self, form_data):
102 103 from rhodecode.lib.celerylib import tasks, run_task
103 104 try:
104 105 new_user = User()
105 106 for k, v in form_data.items():
106 107 if k != 'admin':
107 108 setattr(new_user, k, v)
108 109
109 110 self.sa.add(new_user)
110 111 self.sa.commit()
111 112 body = ('New user registration\n'
112 113 'username: %s\n'
113 114 'email: %s\n')
114 115 body = body % (form_data['username'], form_data['email'])
115 116
116 117 run_task(tasks.send_email, None,
117 118 _('[RhodeCode] New User registration'),
118 119 body)
119 120 except:
120 121 log.error(traceback.format_exc())
121 122 self.sa.rollback()
122 123 raise
123 124
124 125 def update(self, user_id, form_data):
125 126 try:
126 127 new_user = self.get(user_id, cache=False)
127 128 if new_user.username == 'default':
128 129 raise DefaultUserException(
129 130 _("You can't Edit this user since it's"
130 131 " crucial for entire application"))
132
131 133 for k, v in form_data.items():
132 134 if k == 'new_password' and v != '':
133 135 new_user.password = v
134 136 else:
135 137 setattr(new_user, k, v)
136 138
137 139 self.sa.add(new_user)
138 140 self.sa.commit()
139 141 except:
140 142 log.error(traceback.format_exc())
141 143 self.sa.rollback()
142 144 raise
143 145
144 146 def update_my_account(self, user_id, form_data):
145 147 try:
146 148 new_user = self.get(user_id, cache=False)
147 149 if new_user.username == 'default':
148 150 raise DefaultUserException(
149 151 _("You can't Edit this user since it's"
150 152 " crucial for entire application"))
151 153 for k, v in form_data.items():
152 154 if k == 'new_password' and v != '':
153 155 new_user.password = v
154 156 else:
155 157 if k not in ['admin', 'active']:
156 158 setattr(new_user, k, v)
157 159
158 160 self.sa.add(new_user)
159 161 self.sa.commit()
160 162 except:
161 163 log.error(traceback.format_exc())
162 164 self.sa.rollback()
163 165 raise
164 166
165 167 def delete(self, user_id):
166 168 try:
167 169 user = self.get(user_id, cache=False)
168 170 if user.username == 'default':
169 171 raise DefaultUserException(
170 172 _("You can't remove this user since it's"
171 173 " crucial for entire application"))
174 if user.repositories:
175 raise UserOwnsReposException(_('This user still owns %s '
176 'repositories and cannot be '
177 'removed. Switch owners or '
178 'remove those repositories') \
179 % user.repositories)
172 180 self.sa.delete(user)
173 181 self.sa.commit()
174 182 except:
175 183 log.error(traceback.format_exc())
176 184 self.sa.rollback()
177 185 raise
178 186
179 187 def reset_password(self, data):
180 188 from rhodecode.lib.celerylib import tasks, run_task
181 189 run_task(tasks.reset_user_password, data['email'])
182 190
183 191
184 192 def fill_data(self, user):
185 193 """
186 194 Fills user data with those from database and log out user if not
187 195 present in database
188 196 :param user:
189 197 """
190 198
191 199 if not hasattr(user, 'user_id') or user.user_id is None:
192 200 raise Exception('passed in user has to have the user_id attribute')
193 201
194 202
195 203 log.debug('filling auth user data')
196 204 try:
197 205 dbuser = self.get(user.user_id)
198 206 user.username = dbuser.username
199 207 user.is_admin = dbuser.admin
200 208 user.name = dbuser.name
201 209 user.lastname = dbuser.lastname
202 210 user.email = dbuser.email
203 211 except:
204 212 log.error(traceback.format_exc())
205 213 user.is_authenticated = False
206 214
207 215 return user
General Comments 0
You need to be logged in to leave comments. Login now