comparison rhodecode/lib/auth.py @ 3146:c5169e445fb8 beta

Full IP restrictions enabled - short cache query for IP for performance - remove redundant logic - some small css fixes for login form to better show IP restricted message
author Marcin Kuzminski <marcin@python-works.com>
date Fri, 04 Jan 2013 23:34:53 +0100
parents 6c705abed11a
children 3563c47e52fd
comparison
equal deleted inserted replaced
3145:bee09f317edc 3146:c5169e445fb8
44 from rhodecode.lib.auth_ldap import AuthLdap 44 from rhodecode.lib.auth_ldap import AuthLdap
45 45
46 from rhodecode.model import meta 46 from rhodecode.model import meta
47 from rhodecode.model.user import UserModel 47 from rhodecode.model.user import UserModel
48 from rhodecode.model.db import Permission, RhodeCodeSetting, User, UserIpMap 48 from rhodecode.model.db import Permission, RhodeCodeSetting, User, UserIpMap
49 from rhodecode.lib.caching_query import FromCache
49 50
50 log = logging.getLogger(__name__) 51 log = logging.getLogger(__name__)
51 52
52 53
53 class PasswordGenerator(object): 54 class PasswordGenerator(object):
325 self.email = '' 326 self.email = ''
326 self.is_authenticated = False 327 self.is_authenticated = False
327 self.admin = False 328 self.admin = False
328 self.inherit_default_permissions = False 329 self.inherit_default_permissions = False
329 self.permissions = {} 330 self.permissions = {}
330 self.allowed_ips = set()
331 self._api_key = api_key 331 self._api_key = api_key
332 self.propagate_data() 332 self.propagate_data()
333 self._instance = None 333 self._instance = None
334 334
335 def propagate_data(self): 335 def propagate_data(self):
375 if not self.username: 375 if not self.username:
376 self.username = 'None' 376 self.username = 'None'
377 377
378 log.debug('Auth User is now %s' % self) 378 log.debug('Auth User is now %s' % self)
379 user_model.fill_perms(self) 379 user_model.fill_perms(self)
380 log.debug('Filling Allowed IPs')
381 self.allowed_ips = AuthUser.get_allowed_ips(self.user_id)
382 380
383 @property 381 @property
384 def is_admin(self): 382 def is_admin(self):
385 return self.admin 383 return self.admin
384
385 @property
386 def ip_allowed(self):
387 """
388 Checks if ip_addr used in constructor is allowed from defined list of
389 allowed ip_addresses for user
390
391 :returns: boolean, True if ip is in allowed ip range
392 """
393 #check IP
394 allowed_ips = AuthUser.get_allowed_ips(self.user_id, cache=True)
395 if check_ip_access(source_ip=self.ip_addr, allowed_ips=allowed_ips):
396 log.debug('IP:%s is in range of %s' % (self.ip_addr, allowed_ips))
397 return True
398 else:
399 log.info('Access for IP:%s forbidden, '
400 'not in %s' % (self.ip_addr, allowed_ips))
401 return False
386 402
387 def __repr__(self): 403 def __repr__(self):
388 return "<AuthUser('id:%s:%s|%s')>" % (self.user_id, self.username, 404 return "<AuthUser('id:%s:%s|%s')>" % (self.user_id, self.username,
389 self.is_authenticated) 405 self.is_authenticated)
390 406
409 username = cookie_store.get('username') 425 username = cookie_store.get('username')
410 api_key = cookie_store.get('api_key') 426 api_key = cookie_store.get('api_key')
411 return AuthUser(user_id, api_key, username) 427 return AuthUser(user_id, api_key, username)
412 428
413 @classmethod 429 @classmethod
414 def get_allowed_ips(cls, user_id): 430 def get_allowed_ips(cls, user_id, cache=False):
415 _set = set() 431 _set = set()
416 user_ips = UserIpMap.query().filter(UserIpMap.user_id == user_id).all() 432 user_ips = UserIpMap.query().filter(UserIpMap.user_id == user_id)
433 if cache:
434 user_ips = user_ips.options(FromCache("sql_cache_short",
435 "get_user_ips_%s" % user_id))
417 for ip in user_ips: 436 for ip in user_ips:
418 _set.add(ip.ip_addr) 437 _set.add(ip.ip_addr)
419 return _set or set(['0.0.0.0/0']) 438 return _set or set(['0.0.0.0/0'])
420 439
421 440
460 return decorator(self.__wrapper, func) 479 return decorator(self.__wrapper, func)
461 480
462 def __wrapper(self, func, *fargs, **fkwargs): 481 def __wrapper(self, func, *fargs, **fkwargs):
463 cls = fargs[0] 482 cls = fargs[0]
464 user = cls.rhodecode_user 483 user = cls.rhodecode_user
484 loc = "%s:%s" % (cls.__class__.__name__, func.__name__)
485
486 #check IP
487 ip_access_ok = True
488 if not user.ip_allowed:
489 from rhodecode.lib import helpers as h
490 h.flash(h.literal(_('IP %s not allowed' % (user.ip_addr))),
491 category='warning')
492 ip_access_ok = False
465 493
466 api_access_ok = False 494 api_access_ok = False
467 if self.api_access: 495 if self.api_access:
468 log.debug('Checking API KEY access for %s' % cls) 496 log.debug('Checking API KEY access for %s' % cls)
469 if user.api_key == request.GET.get('api_key'): 497 if user.api_key == request.GET.get('api_key'):
470 api_access_ok = True 498 api_access_ok = True
471 else: 499 else:
472 log.debug("API KEY token not valid") 500 log.debug("API KEY token not valid")
473 loc = "%s:%s" % (cls.__class__.__name__, func.__name__) 501
474 log.debug('Checking if %s is authenticated @ %s' % (user.username, loc)) 502 log.debug('Checking if %s is authenticated @ %s' % (user.username, loc))
475 if user.is_authenticated or api_access_ok: 503 if (user.is_authenticated or api_access_ok) and ip_access_ok:
476 reason = 'RegularAuth' if user.is_authenticated else 'APIAuth' 504 reason = 'RegularAuth' if user.is_authenticated else 'APIAuth'
477 log.info('user %s is authenticated and granted access to %s ' 505 log.info('user %s is authenticated and granted access to %s '
478 'using %s' % (user.username, loc, reason) 506 'using %s' % (user.username, loc, reason)
479 ) 507 )
480 return func(*fargs, **fkwargs) 508 return func(*fargs, **fkwargs)