Mercurial > kallithea
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) |