##// END OF EJS Templates
Major rewrite of auth objects. Moved parts of filling user data into user model....
marcink -
r1117:6eb5bb24 beta
parent child Browse files
Show More
@@ -36,8 +36,7 b' from pylons.i18n.translation import _'
36
36
37 from rhodecode.lib.exceptions import DefaultUserException, UserOwnsReposException
37 from rhodecode.lib.exceptions import DefaultUserException, UserOwnsReposException
38 from rhodecode.lib import helpers as h
38 from rhodecode.lib import helpers as h
39 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \
39 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
40 fill_perms
41 from rhodecode.lib.base import BaseController, render
40 from rhodecode.lib.base import BaseController, render
42
41
43 from rhodecode.model.db import User
42 from rhodecode.model.db import User
@@ -157,14 +156,15 b' class UsersController(BaseController):'
157 def edit(self, id, format='html'):
156 def edit(self, id, format='html'):
158 """GET /users/id/edit: Form to edit an existing item"""
157 """GET /users/id/edit: Form to edit an existing item"""
159 # url('edit_user', id=ID)
158 # url('edit_user', id=ID)
160 c.user = self.sa.query(User).get(id)
159 user_model = UserModel()
160 c.user = user_model.get(id)
161 if not c.user:
161 if not c.user:
162 return redirect(url('users'))
162 return redirect(url('users'))
163 if c.user.username == 'default':
163 if c.user.username == 'default':
164 h.flash(_("You can't edit this user"), category='warning')
164 h.flash(_("You can't edit this user"), category='warning')
165 return redirect(url('users'))
165 return redirect(url('users'))
166 c.user.permissions = {}
166 c.user.permissions = {}
167 c.granted_permissions = fill_perms(c.user).permissions['global']
167 c.granted_permissions = user_model.fill_perms(c.user).permissions['global']
168
168
169 defaults = c.user.get_dict()
169 defaults = c.user.get_dict()
170
170
@@ -36,8 +36,7 b' from pylons.i18n.translation import _'
36
36
37 from rhodecode.lib.exceptions import DefaultUserException, UserOwnsReposException
37 from rhodecode.lib.exceptions import DefaultUserException, UserOwnsReposException
38 from rhodecode.lib import helpers as h
38 from rhodecode.lib import helpers as h
39 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \
39 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
40 fill_perms
41 from rhodecode.lib.base import BaseController, render
40 from rhodecode.lib.base import BaseController, render
42
41
43 from rhodecode.model.db import User, UsersGroup
42 from rhodecode.model.db import User, UsersGroup
@@ -49,6 +49,7 b' class JournalController(BaseController):'
49 @LoginRequired()
49 @LoginRequired()
50 def __before__(self):
50 def __before__(self):
51 super(JournalController, self).__before__()
51 super(JournalController, self).__before__()
52 c.rhodecode_user = self.rhodecode_user
52 self.title = _('%s public journal %s feed') % (c.rhodecode_name, '%s')
53 self.title = _('%s public journal %s feed') % (c.rhodecode_name, '%s')
53 self.language = 'en-us'
54 self.language = 'en-us'
54 self.ttl = "5"
55 self.ttl = "5"
@@ -60,7 +61,7 b' class JournalController(BaseController):'
60 p = int(request.params.get('page', 1))
61 p = int(request.params.get('page', 1))
61
62
62 c.following = self.sa.query(UserFollowing)\
63 c.following = self.sa.query(UserFollowing)\
63 .filter(UserFollowing.user_id == c.rhodecode_user.user_id)\
64 .filter(UserFollowing.user_id == self.rhodecode_user.user_id)\
64 .options(joinedload(UserFollowing.follows_repository))\
65 .options(joinedload(UserFollowing.follows_repository))\
65 .all()
66 .all()
66
67
@@ -126,7 +127,7 b' class JournalController(BaseController):'
126 if user_id:
127 if user_id:
127 try:
128 try:
128 self.scm_model.toggle_following_user(user_id,
129 self.scm_model.toggle_following_user(user_id,
129 c.rhodecode_user.user_id)
130 self.rhodecode_user.user_id)
130 return 'ok'
131 return 'ok'
131 except:
132 except:
132 raise HTTPInternalServerError()
133 raise HTTPInternalServerError()
@@ -135,7 +136,7 b' class JournalController(BaseController):'
135 if repo_id:
136 if repo_id:
136 try:
137 try:
137 self.scm_model.toggle_following_repo(repo_id,
138 self.scm_model.toggle_following_repo(repo_id,
138 c.rhodecode_user.user_id)
139 self.rhodecode_user.user_id)
139 return 'ok'
140 return 'ok'
140 except:
141 except:
141 raise HTTPInternalServerError()
142 raise HTTPInternalServerError()
@@ -152,7 +153,7 b' class JournalController(BaseController):'
152 p = int(request.params.get('page', 1))
153 p = int(request.params.get('page', 1))
153
154
154 c.following = self.sa.query(UserFollowing)\
155 c.following = self.sa.query(UserFollowing)\
155 .filter(UserFollowing.user_id == c.rhodecode_user.user_id)\
156 .filter(UserFollowing.user_id == self.rhodecode_user.user_id)\
156 .options(joinedload(UserFollowing.follows_repository))\
157 .options(joinedload(UserFollowing.follows_repository))\
157 .all()
158 .all()
158
159
@@ -174,7 +175,7 b' class JournalController(BaseController):'
174 Produce an atom-1.0 feed via feedgenerator module
175 Produce an atom-1.0 feed via feedgenerator module
175 """
176 """
176 c.following = self.sa.query(UserFollowing)\
177 c.following = self.sa.query(UserFollowing)\
177 .filter(UserFollowing.user_id == c.rhodecode_user.user_id)\
178 .filter(UserFollowing.user_id == self.rhodecode_user.user_id)\
178 .options(joinedload(UserFollowing.follows_repository))\
179 .options(joinedload(UserFollowing.follows_repository))\
179 .all()
180 .all()
180
181
@@ -207,7 +208,7 b' class JournalController(BaseController):'
207 Produce an rss2 feed via feedgenerator module
208 Produce an rss2 feed via feedgenerator module
208 """
209 """
209 c.following = self.sa.query(UserFollowing)\
210 c.following = self.sa.query(UserFollowing)\
210 .filter(UserFollowing.user_id == c.rhodecode_user.user_id)\
211 .filter(UserFollowing.user_id == self.rhodecode_user.user_id)\
211 .options(joinedload(UserFollowing.follows_repository))\
212 .options(joinedload(UserFollowing.follows_repository))\
212 .all()
213 .all()
213
214
@@ -62,19 +62,17 b' class LoginController(BaseController):'
62 login_form = LoginForm()
62 login_form = LoginForm()
63 try:
63 try:
64 c.form_result = login_form.to_python(dict(request.POST))
64 c.form_result = login_form.to_python(dict(request.POST))
65 #form checks for username/password, now we're authenticated
65 username = c.form_result['username']
66 username = c.form_result['username']
66 user = UserModel().get_by_username(username, case_insensitive=True)
67 user = UserModel().get_by_username(username,
67 auth_user = AuthUser()
68 case_insensitive=True)
68 auth_user.username = user.username
69 auth_user = AuthUser(user.user_id)
69 auth_user.is_authenticated = True
70 auth_user.set_authenticated()
70 auth_user.is_admin = user.admin
71 auth_user.user_id = user.user_id
72 auth_user.name = user.name
73 auth_user.lastname = user.lastname
74 session['rhodecode_user'] = auth_user
71 session['rhodecode_user'] = auth_user
75 session.save()
72 session.save()
76 log.info('user %s is now authenticated', username)
77
73
74 log.info('user %s is now authenticated and stored in session',
75 username)
78 user.update_lastlogin()
76 user.update_lastlogin()
79
77
80 if c.came_from:
78 if c.came_from:
@@ -146,7 +144,7 b' class LoginController(BaseController):'
146 return render('/password_reset.html')
144 return render('/password_reset.html')
147
145
148 def logout(self):
146 def logout(self):
149 session['rhodecode_user'] = AuthUser()
147 del session['rhodecode_user']
150 session.save()
148 session.save()
151 log.info('Logging out and setting user as Empty')
149 log.info('Logging out and setting user as Empty')
152 redirect(url('home'))
150 redirect(url('home'))
@@ -42,19 +42,11 b' from rhodecode.lib.auth_ldap import Auth'
42
42
43 from rhodecode.model import meta
43 from rhodecode.model import meta
44 from rhodecode.model.user import UserModel
44 from rhodecode.model.user import UserModel
45 from rhodecode.model.db import User, RepoToPerm, Repository, Permission, \
45 from rhodecode.model.db import Permission
46 UserToPerm, UsersGroupToPerm, UsersGroupMember
47
46
48
47
49 log = logging.getLogger(__name__)
48 log = logging.getLogger(__name__)
50
49
51
52 PERM_WEIGHTS = {'repository.none':0,
53 'repository.read':1,
54 'repository.write':3,
55 'repository.admin':3}
56
57
58 class PasswordGenerator(object):
50 class PasswordGenerator(object):
59 """This is a simple class for generating password from
51 """This is a simple class for generating password from
60 different sets of characters
52 different sets of characters
@@ -185,21 +177,66 b' def authenticate(username, password):'
185 return False
177 return False
186
178
187 class AuthUser(object):
179 class AuthUser(object):
188 """A simple object that handles a mercurial username for authentication
180 """
181 A simple object that handles all attributes of user in RhodeCode
182
183 It does lookup based on API key,given user, or user present in session
184 Then it fills all required information for such user. It also checks if
185 anonymous access is enabled and if so, it returns default user as logged
186 in
189 """
187 """
190
188
191 def __init__(self):
189 def __init__(self, user_id=None, api_key=None):
190
191 self.user_id = user_id
192 self.api_key = api_key
193
192 self.username = 'None'
194 self.username = 'None'
193 self.name = ''
195 self.name = ''
194 self.lastname = ''
196 self.lastname = ''
195 self.email = ''
197 self.email = ''
196 self.user_id = None
197 self.is_authenticated = False
198 self.is_authenticated = False
198 self.is_admin = False
199 self.admin = False
199 self.permissions = {}
200 self.permissions = {}
201 self.propagate_data()
202
203
204 def propagate_data(self):
205 user_model = UserModel()
206 if self.api_key:
207 #try go get user by api key
208 log.debug('Auth User lookup by API KEY %s', self.api_key)
209 user_model.fill_data(self, api_key=self.api_key)
210 else:
211 log.debug('Auth User lookup by USER ID %s', self.user_id)
212 self.anonymous_user = user_model.get_by_username('default', cache=True)
213
214 if self.user_id is not None and self.user_id != self.anonymous_user.user_id:
215 user_model.fill_data(self, user_id=self.user_id)
216 else:
217 if self.anonymous_user.active is True:
218 user_model.fill_data(self, user_id=self.anonymous_user.user_id)
219 #then we set this user is logged in
220 self.is_authenticated = True
221 else:
222 self.is_authenticated = False
223
224 log.debug('Auth User is now %s', self)
225 user_model.fill_perms(self)
226
227 @property
228 def is_admin(self):
229 return self.admin
200
230
201 def __repr__(self):
231 def __repr__(self):
202 return "<AuthUser('id:%s:%s')>" % (self.user_id, self.username)
232 return "<AuthUser('id:%s:%s|%s')>" % (self.user_id, self.username,
233 self.is_authenticated)
234
235 def set_authenticated(self, authenticated=True):
236
237 if self.user_id != self.anonymous_user.user_id:
238 self.is_authenticated = authenticated
239
203
240
204 def set_available_permissions(config):
241 def set_available_permissions(config):
205 """This function will propagate pylons globals with all available defined
242 """This function will propagate pylons globals with all available defined
@@ -221,144 +258,42 b' def set_available_permissions(config):'
221
258
222 config['available_permissions'] = [x.permission_name for x in all_perms]
259 config['available_permissions'] = [x.permission_name for x in all_perms]
223
260
224 def fill_perms(user):
225 """Fills user permission attribute with permissions taken from database
226 works for permissions given for repositories, and for permissions that
227 as part of beeing group member
228
229 :param user: user instance to fill his perms
230 """
231
232 sa = meta.Session()
233 user.permissions['repositories'] = {}
234 user.permissions['global'] = set()
235
236 #===========================================================================
237 # fetch default permissions
238 #===========================================================================
239 default_user = UserModel().get_by_username('default', cache=True)
240
241 default_perms = sa.query(RepoToPerm, Repository, Permission)\
242 .join((Repository, RepoToPerm.repository_id == Repository.repo_id))\
243 .join((Permission, RepoToPerm.permission_id == Permission.permission_id))\
244 .filter(RepoToPerm.user == default_user).all()
245
246 if user.is_admin:
247 #=======================================================================
248 # #admin have all default rights set to admin
249 #=======================================================================
250 user.permissions['global'].add('hg.admin')
251
252 for perm in default_perms:
253 p = 'repository.admin'
254 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
255
256 else:
257 #=======================================================================
258 # set default permissions
259 #=======================================================================
260
261 #default global
262 default_global_perms = sa.query(UserToPerm)\
263 .filter(UserToPerm.user == sa.query(User)\
264 .filter(User.username == 'default').one())
265
266 for perm in default_global_perms:
267 user.permissions['global'].add(perm.permission.permission_name)
268
269 #default for repositories
270 for perm in default_perms:
271 if perm.Repository.private and not perm.Repository.user_id == user.user_id:
272 #disable defaults for private repos,
273 p = 'repository.none'
274 elif perm.Repository.user_id == user.user_id:
275 #set admin if owner
276 p = 'repository.admin'
277 else:
278 p = perm.Permission.permission_name
279
280 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
281
282 #=======================================================================
283 # overwrite default with user permissions if any
284 #=======================================================================
285 user_perms = sa.query(RepoToPerm, Permission, Repository)\
286 .join((Repository, RepoToPerm.repository_id == Repository.repo_id))\
287 .join((Permission, RepoToPerm.permission_id == Permission.permission_id))\
288 .filter(RepoToPerm.user_id == user.user_id).all()
289
290 for perm in user_perms:
291 if perm.Repository.user_id == user.user_id:#set admin if owner
292 p = 'repository.admin'
293 else:
294 p = perm.Permission.permission_name
295 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
296
297
298 #=======================================================================
299 # check if user is part of groups for this repository and fill in
300 # (or replace with higher) permissions
301 #=======================================================================
302 user_perms_from_users_groups = sa.query(UsersGroupToPerm, Permission, Repository,)\
303 .join((Repository, UsersGroupToPerm.repository_id == Repository.repo_id))\
304 .join((Permission, UsersGroupToPerm.permission_id == Permission.permission_id))\
305 .join((UsersGroupMember, UsersGroupToPerm.users_group_id == UsersGroupMember.users_group_id))\
306 .filter(UsersGroupMember.user_id == user.user_id).all()
307
308 for perm in user_perms_from_users_groups:
309 p = perm.Permission.permission_name
310 cur_perm = user.permissions['repositories'][perm.UsersGroupToPerm.repository.repo_name]
311 #overwrite permission only if it's greater than permission given from other sources
312 if PERM_WEIGHTS[p] > PERM_WEIGHTS[cur_perm]:
313 user.permissions['repositories'][perm.UsersGroupToPerm.repository.repo_name] = p
314
315 meta.Session.remove()
316 return user
317
318 def get_user(session):
319 """Gets user from session, and wraps permissions into user
320
321 :param session:
322 """
323 user = session.get('rhodecode_user', AuthUser())
324 #if the user is not logged in we check for anonymous access
325 #if user is logged and it's a default user check if we still have anonymous
326 #access enabled
327 if user.user_id is None or user.username == 'default':
328 anonymous_user = UserModel().get_by_username('default', cache=True)
329 if anonymous_user.active is True:
330 #then we set this user is logged in
331 user.is_authenticated = True
332 user.user_id = anonymous_user.user_id
333 else:
334 user.is_authenticated = False
335
336 if user.is_authenticated:
337 user = UserModel().fill_data(user)
338
339 user = fill_perms(user)
340 session['rhodecode_user'] = user
341 session.save()
342 return user
343
344 #===============================================================================
261 #===============================================================================
345 # CHECK DECORATORS
262 # CHECK DECORATORS
346 #===============================================================================
263 #===============================================================================
347 class LoginRequired(object):
264 class LoginRequired(object):
348 """Must be logged in to execute this function else
265 """
349 redirect to login page"""
266 Must be logged in to execute this function else
267 redirect to login page
268
269 :param api_access: if enabled this checks only for valid auth token
270 and grants access based on valid token
271 """
272
273 def __init__(self, api_access=False):
274 self.api_access = api_access
350
275
351 def __call__(self, func):
276 def __call__(self, func):
352 return decorator(self.__wrapper, func)
277 return decorator(self.__wrapper, func)
353
278
354 def __wrapper(self, func, *fargs, **fkwargs):
279 def __wrapper(self, func, *fargs, **fkwargs):
355 user = session.get('rhodecode_user', AuthUser())
280 cls = fargs[0]
356 log.debug('Checking login required for user:%s', user.username)
281 user = cls.rhodecode_user
357 if user.is_authenticated:
282
283 api_access_ok = False
284 if self.api_access:
285 log.debug('Checking API KEY access for %s', cls)
286 if user.api_key == request.GET.get('api_key'):
287 api_access_ok = True
288 else:
289 log.debug("API KEY token not valid")
290
291 log.debug('Checking if %s is authenticated @ %s', user.username, cls)
292 if user.is_authenticated or api_access_ok:
358 log.debug('user %s is authenticated', user.username)
293 log.debug('user %s is authenticated', user.username)
359 return func(*fargs, **fkwargs)
294 return func(*fargs, **fkwargs)
360 else:
295 else:
361 log.warn('user %s not authenticated', user.username)
296 log.warn('user %s NOT authenticated', user.username)
362
297
363 p = ''
298 p = ''
364 if request.environ.get('SCRIPT_NAME') != '/':
299 if request.environ.get('SCRIPT_NAME') != '/':
@@ -379,10 +314,12 b' class NotAnonymous(object):'
379 return decorator(self.__wrapper, func)
314 return decorator(self.__wrapper, func)
380
315
381 def __wrapper(self, func, *fargs, **fkwargs):
316 def __wrapper(self, func, *fargs, **fkwargs):
382 user = session.get('rhodecode_user', AuthUser())
317 cls = fargs[0]
383 log.debug('Checking if user is not anonymous')
318 self.user = cls.rhodecode_user
384
319
385 anonymous = user.username == 'default'
320 log.debug('Checking if user is not anonymous @%s', cls)
321
322 anonymous = self.user.username == 'default'
386
323
387 if anonymous:
324 if anonymous:
388 p = ''
325 p = ''
@@ -401,7 +338,7 b' class NotAnonymous(object):'
401 return func(*fargs, **fkwargs)
338 return func(*fargs, **fkwargs)
402
339
403 class PermsDecorator(object):
340 class PermsDecorator(object):
404 """Base class for decorators"""
341 """Base class for controller decorators"""
405
342
406 def __init__(self, *required_perms):
343 def __init__(self, *required_perms):
407 available_perms = config['available_permissions']
344 available_perms = config['available_permissions']
@@ -416,22 +353,19 b' class PermsDecorator(object):'
416
353
417
354
418 def __wrapper(self, func, *fargs, **fkwargs):
355 def __wrapper(self, func, *fargs, **fkwargs):
419 # _wrapper.__name__ = func.__name__
356 cls = fargs[0]
420 # _wrapper.__dict__.update(func.__dict__)
357 self.user = cls.rhodecode_user
421 # _wrapper.__doc__ = func.__doc__
422 self.user = session.get('rhodecode_user', AuthUser())
423 self.user_perms = self.user.permissions
358 self.user_perms = self.user.permissions
424 log.debug('checking %s permissions %s for %s %s',
359 log.debug('checking %s permissions %s for %s %s',
425 self.__class__.__name__, self.required_perms, func.__name__,
360 self.__class__.__name__, self.required_perms, cls,
426 self.user)
361 self.user)
427
362
428 if self.check_permissions():
363 if self.check_permissions():
429 log.debug('Permission granted for %s %s', func.__name__, self.user)
364 log.debug('Permission granted for %s %s', cls, self.user)
430
431 return func(*fargs, **fkwargs)
365 return func(*fargs, **fkwargs)
432
366
433 else:
367 else:
434 log.warning('Permission denied for %s %s', func.__name__, self.user)
368 log.warning('Permission denied for %s %s', cls, self.user)
435 #redirect with forbidden ret code
369 #redirect with forbidden ret code
436 return abort(403)
370 return abort(403)
437
371
@@ -516,18 +450,18 b' class PermsFunction(object):'
516 if not user:
450 if not user:
517 return False
451 return False
518 self.user_perms = user.permissions
452 self.user_perms = user.permissions
519 self.granted_for = user.username
453 self.granted_for = user
520 log.debug('checking %s %s %s', self.__class__.__name__,
454 log.debug('checking %s %s %s', self.__class__.__name__,
521 self.required_perms, user)
455 self.required_perms, user)
522
456
523 if self.check_permissions():
457 if self.check_permissions():
524 log.debug('Permission granted for %s @ %s %s', self.granted_for,
458 log.debug('Permission granted %s @ %s', self.granted_for,
525 check_Location, user)
459 check_Location or 'unspecified location')
526 return True
460 return True
527
461
528 else:
462 else:
529 log.warning('Permission denied for %s @ %s %s', self.granted_for,
463 log.warning('Permission denied for %s @ %s', self.granted_for,
530 check_Location, user)
464 check_Location or 'unspecified location')
531 return False
465 return False
532
466
533 def check_permissions(self):
467 def check_permissions(self):
@@ -595,14 +529,9 b' class HasPermissionAnyMiddleware(object)'
595 self.required_perms = set(perms)
529 self.required_perms = set(perms)
596
530
597 def __call__(self, user, repo_name):
531 def __call__(self, user, repo_name):
598 usr = AuthUser()
532 usr = AuthUser(user.user_id)
599 usr.user_id = user.user_id
600 usr.username = user.username
601 usr.is_admin = user.admin
602
603 try:
533 try:
604 self.user_perms = set([fill_perms(usr)\
534 self.user_perms = set([usr.permissions['repositories'][repo_name]])
605 .permissions['repositories'][repo_name]])
606 except:
535 except:
607 self.user_perms = set()
536 self.user_perms = set()
608 self.granted_for = ''
537 self.granted_for = ''
@@ -6,7 +6,7 b' from pylons import config, tmpl_context '
6 from pylons.controllers import WSGIController
6 from pylons.controllers import WSGIController
7 from pylons.templating import render_mako as render
7 from pylons.templating import render_mako as render
8 from rhodecode import __version__
8 from rhodecode import __version__
9 from rhodecode.lib import auth
9 from rhodecode.lib.auth import AuthUser
10 from rhodecode.lib.utils import get_repo_slug
10 from rhodecode.lib.utils import get_repo_slug
11 from rhodecode.model import meta
11 from rhodecode.model import meta
12 from rhodecode.model.scm import ScmModel
12 from rhodecode.model.scm import ScmModel
@@ -34,7 +34,14 b' class BaseController(WSGIController):'
34 # available in environ['pylons.routes_dict']
34 # available in environ['pylons.routes_dict']
35 try:
35 try:
36 #putting this here makes sure that we update permissions every time
36 #putting this here makes sure that we update permissions every time
37 self.rhodecode_user = c.rhodecode_user = auth.get_user(session)
37 api_key = request.GET.get('api_key')
38 user_id = getattr(session.get('rhodecode_user'), 'user_id', None)
39 self.rhodecode_user = c.rhodecode_user = AuthUser(user_id, api_key)
40 self.rhodecode_user.set_authenticated(
41 getattr(session.get('rhodecode_user'),
42 'is_authenticated', False))
43 session['rhodecode_user'] = self.rhodecode_user
44 session.save()
38 return WSGIController.__call__(self, environ, start_response)
45 return WSGIController.__call__(self, environ, start_response)
39 finally:
46 finally:
40 meta.Session.remove()
47 meta.Session.remove()
@@ -32,8 +32,8 b' from pylons.i18n.translation import _'
32
32
33 from rhodecode.model import BaseModel
33 from rhodecode.model import BaseModel
34 from rhodecode.model.caching_query import FromCache
34 from rhodecode.model.caching_query import FromCache
35 from rhodecode.model.db import User
35 from rhodecode.model.db import User, RepoToPerm, Repository, Permission, \
36
36 UserToPerm, UsersGroupToPerm, UsersGroupMember
37 from rhodecode.lib.exceptions import DefaultUserException, UserOwnsReposException
37 from rhodecode.lib.exceptions import DefaultUserException, UserOwnsReposException
38
38
39 from sqlalchemy.exc import DatabaseError
39 from sqlalchemy.exc import DatabaseError
@@ -41,6 +41,11 b' from rhodecode.lib import generate_api_k'
41
41
42 log = logging.getLogger(__name__)
42 log = logging.getLogger(__name__)
43
43
44 PERM_WEIGHTS = {'repository.none':0,
45 'repository.read':1,
46 'repository.write':3,
47 'repository.admin':3}
48
44 class UserModel(BaseModel):
49 class UserModel(BaseModel):
45
50
46 def get(self, user_id, cache=False):
51 def get(self, user_id, cache=False):
@@ -63,6 +68,16 b' class UserModel(BaseModel):'
63 "get_user_%s" % username))
68 "get_user_%s" % username))
64 return user.scalar()
69 return user.scalar()
65
70
71
72 def get_by_api_key(self, api_key, cache=False):
73
74 user = self.sa.query(User)\
75 .filter(User.api_key == api_key)
76 if cache:
77 user = user.options(FromCache("sql_cache_short",
78 "get_user_%s" % api_key))
79 return user.scalar()
80
66 def create(self, form_data):
81 def create(self, form_data):
67 try:
82 try:
68 new_user = User()
83 new_user = User()
@@ -204,27 +219,125 b' class UserModel(BaseModel):'
204 run_task(tasks.reset_user_password, data['email'])
219 run_task(tasks.reset_user_password, data['email'])
205
220
206
221
207 def fill_data(self, user):
222 def fill_data(self, auth_user, user_id=None, api_key=None):
208 """
223 """
209 Fills user data with those from database and log out user if not
224 Fetches auth_user by user_id,or api_key if present.
225 Fills auth_user attributes with those taken from database.
226 Additionally set's is_authenitated if lookup fails
210 present in database
227 present in database
211 :param user:
228
229 :param auth_user: instance of user to set attributes
230 :param user_id: user id to fetch by
231 :param api_key: api key to fetch by
212 """
232 """
233 if not user_id and not not api_key:
234 raise Exception('You need to pass user_id or api_key')
213
235
214 if not hasattr(user, 'user_id') or user.user_id is None:
236 try:
215 raise Exception('passed in user has to have the user_id attribute')
237 if api_key:
238 dbuser = self.get_by_api_key(api_key)
239 else:
240 dbuser = self.get(user_id)
241
242 log.debug('filling %s data', dbuser)
243 for k, v in dbuser.get_dict().items():
244 setattr(auth_user, k, v)
245
246 except:
247 log.error(traceback.format_exc())
248 auth_user.is_authenticated = False
249
250 return auth_user
216
251
217
252
218 log.debug('filling auth user data')
253 def fill_perms(self, user):
219 try:
254 """Fills user permission attribute with permissions taken from database
220 dbuser = self.get(user.user_id)
255 works for permissions given for repositories, and for permissions that
221 user.username = dbuser.username
256 as part of beeing group member
222 user.is_admin = dbuser.admin
257
223 user.name = dbuser.name
258 :param user: user instance to fill his perms
224 user.lastname = dbuser.lastname
259 """
225 user.email = dbuser.email
260
226 except:
261 user.permissions['repositories'] = {}
227 log.error(traceback.format_exc())
262 user.permissions['global'] = set()
228 user.is_authenticated = False
263
264 #===========================================================================
265 # fetch default permissions
266 #===========================================================================
267 default_user = self.get_by_username('default', cache=True)
268
269 default_perms = self.sa.query(RepoToPerm, Repository, Permission)\
270 .join((Repository, RepoToPerm.repository_id == Repository.repo_id))\
271 .join((Permission, RepoToPerm.permission_id == Permission.permission_id))\
272 .filter(RepoToPerm.user == default_user).all()
273
274 if user.is_admin:
275 #=======================================================================
276 # #admin have all default rights set to admin
277 #=======================================================================
278 user.permissions['global'].add('hg.admin')
279
280 for perm in default_perms:
281 p = 'repository.admin'
282 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
283
284 else:
285 #=======================================================================
286 # set default permissions
287 #=======================================================================
288
289 #default global
290 default_global_perms = self.sa.query(UserToPerm)\
291 .filter(UserToPerm.user == self.sa.query(User)\
292 .filter(User.username == 'default').one())
293
294 for perm in default_global_perms:
295 user.permissions['global'].add(perm.permission.permission_name)
296
297 #default for repositories
298 for perm in default_perms:
299 if perm.Repository.private and not perm.Repository.user_id == user.user_id:
300 #diself.sable defaults for private repos,
301 p = 'repository.none'
302 elif perm.Repository.user_id == user.user_id:
303 #set admin if owner
304 p = 'repository.admin'
305 else:
306 p = perm.Permission.permission_name
307
308 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
309
310 #=======================================================================
311 # overwrite default with user permissions if any
312 #=======================================================================
313 user_perms = self.sa.query(RepoToPerm, Permission, Repository)\
314 .join((Repository, RepoToPerm.repository_id == Repository.repo_id))\
315 .join((Permission, RepoToPerm.permission_id == Permission.permission_id))\
316 .filter(RepoToPerm.user_id == user.user_id).all()
317
318 for perm in user_perms:
319 if perm.Repository.user_id == user.user_id:#set admin if owner
320 p = 'repository.admin'
321 else:
322 p = perm.Permission.permission_name
323 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
324
325
326 #=======================================================================
327 # check if user is part of groups for this repository and fill in
328 # (or replace with higher) permissions
329 #=======================================================================
330 user_perms_from_users_groups = self.sa.query(UsersGroupToPerm, Permission, Repository,)\
331 .join((Repository, UsersGroupToPerm.repository_id == Repository.repo_id))\
332 .join((Permission, UsersGroupToPerm.permission_id == Permission.permission_id))\
333 .join((UsersGroupMember, UsersGroupToPerm.users_group_id == UsersGroupMember.users_group_id))\
334 .filter(UsersGroupMember.user_id == user.user_id).all()
335
336 for perm in user_perms_from_users_groups:
337 p = perm.Permission.permission_name
338 cur_perm = user.permissions['repositories'][perm.UsersGroupToPerm.repository.repo_name]
339 #overwrite permission only if it's greater than permission given from other sources
340 if PERM_WEIGHTS[p] > PERM_WEIGHTS[cur_perm]:
341 user.permissions['repositories'][perm.UsersGroupToPerm.repository.repo_name] = p
229
342
230 return user
343 return user
General Comments 0
You need to be logged in to leave comments. Login now