Show More
@@ -43,7 +43,7 b' from webob.exc import HTTPNotFound, HTTP' | |||||
43 | HTTPBadRequest, HTTPError |
|
43 | HTTPBadRequest, HTTPError | |
44 |
|
44 | |||
45 | from rhodecode.model.db import User |
|
45 | from rhodecode.model.db import User | |
46 |
from rhodecode.lib.auth import AuthUser |
|
46 | from rhodecode.lib.auth import AuthUser | |
47 | from rhodecode.lib.base import _get_ip_addr, _get_access_path |
|
47 | from rhodecode.lib.base import _get_ip_addr, _get_access_path | |
48 | from rhodecode.lib.utils2 import safe_unicode |
|
48 | from rhodecode.lib.utils2 import safe_unicode | |
49 |
|
49 | |||
@@ -148,17 +148,15 b' class JSONRPCController(WSGIController):' | |||||
148 | if u is None: |
|
148 | if u is None: | |
149 | return jsonrpc_error(retid=self._req_id, |
|
149 | return jsonrpc_error(retid=self._req_id, | |
150 | message='Invalid API KEY') |
|
150 | message='Invalid API KEY') | |
|
151 | ||||
151 | #check if we are allowed to use this IP |
|
152 | #check if we are allowed to use this IP | |
152 | allowed_ips = AuthUser.get_allowed_ips(u.user_id) |
|
153 | auth_u = AuthUser(u.user_id, self._req_api_key, ip_addr=ip_addr) | |
153 | if check_ip_access(source_ip=ip_addr, allowed_ips=allowed_ips) is False: |
|
154 | if not auth_u.ip_allowed: | |
154 | log.info('Access for IP:%s forbidden, ' |
|
|||
155 | 'not in %s' % (ip_addr, allowed_ips)) |
|
|||
156 | return jsonrpc_error(retid=self._req_id, |
|
155 | return jsonrpc_error(retid=self._req_id, | |
157 | message='request from IP:%s not allowed' % (ip_addr)) |
|
156 | message='request from IP:%s not allowed' % (ip_addr)) | |
158 | else: |
|
157 | else: | |
159 | log.info('Access for IP:%s allowed' % (ip_addr)) |
|
158 | log.info('Access for IP:%s allowed' % (ip_addr)) | |
160 |
|
159 | |||
161 | auth_u = AuthUser(u.user_id, self._req_api_key, ip_addr=ip_addr) |
|
|||
162 | except Exception, e: |
|
160 | except Exception, e: | |
163 | return jsonrpc_error(retid=self._req_id, |
|
161 | return jsonrpc_error(retid=self._req_id, | |
164 | message='Invalid API KEY') |
|
162 | message='Invalid API KEY') |
@@ -54,10 +54,9 b' class LoginController(BaseController):' | |||||
54 | def index(self): |
|
54 | def index(self): | |
55 | # redirect if already logged in |
|
55 | # redirect if already logged in | |
56 | c.came_from = request.GET.get('came_from') |
|
56 | c.came_from = request.GET.get('came_from') | |
57 |
|
57 | not_default = self.rhodecode_user.username != 'default' | ||
58 |
i |
|
58 | ip_allowed = self.rhodecode_user.ip_allowed | |
59 | and self.rhodecode_user.username != 'default': |
|
59 | if self.rhodecode_user.is_authenticated and not_default and ip_allowed: | |
60 |
|
||||
61 | return redirect(url('home')) |
|
60 | return redirect(url('home')) | |
62 |
|
61 | |||
63 | if request.POST: |
|
62 | if request.POST: |
@@ -46,6 +46,7 b' from rhodecode.lib.auth_ldap import Auth' | |||||
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 | |||
@@ -327,7 +328,6 b' class AuthUser(object):' | |||||
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 | |
@@ -377,13 +377,29 b' class AuthUser(object):' | |||||
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 | |
386 |
|
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 | |||
|
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) | |
@@ -411,9 +427,12 b' class AuthUser(object):' | |||||
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) |
|
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']) | |
@@ -462,6 +481,15 b' class LoginRequired(object):' | |||||
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: | |
@@ -470,9 +498,9 b' class LoginRequired(object):' | |||||
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) |
@@ -20,7 +20,7 b' from rhodecode import __version__, BACKE' | |||||
20 | from rhodecode.lib.utils2 import str2bool, safe_unicode, AttributeDict,\ |
|
20 | from rhodecode.lib.utils2 import str2bool, safe_unicode, AttributeDict,\ | |
21 | safe_str, safe_int |
|
21 | safe_str, safe_int | |
22 | from rhodecode.lib.auth import AuthUser, get_container_username, authfunc,\ |
|
22 | from rhodecode.lib.auth import AuthUser, get_container_username, authfunc,\ | |
23 |
HasPermissionAnyMiddleware, CookieStoreWrapper |
|
23 | HasPermissionAnyMiddleware, CookieStoreWrapper | |
24 | from rhodecode.lib.utils import get_repo_slug, invalidate_cache |
|
24 | from rhodecode.lib.utils import get_repo_slug, invalidate_cache | |
25 | from rhodecode.model import meta |
|
25 | from rhodecode.model import meta | |
26 |
|
26 | |||
@@ -146,10 +146,8 b' class BaseVCSController(object):' | |||||
146 | :param repo_name: repository name |
|
146 | :param repo_name: repository name | |
147 | """ |
|
147 | """ | |
148 | #check IP |
|
148 | #check IP | |
149 | allowed_ips = AuthUser.get_allowed_ips(user.user_id) |
|
149 | authuser = AuthUser(user_id=user.user_id, ip_addr=ip_addr) | |
150 | if check_ip_access(source_ip=ip_addr, allowed_ips=allowed_ips) is False: |
|
150 | if not authuser.ip_allowed: | |
151 | log.info('Access for IP:%s forbidden, ' |
|
|||
152 | 'not in %s' % (ip_addr, allowed_ips)) |
|
|||
153 | return False |
|
151 | return False | |
154 | else: |
|
152 | else: | |
155 | log.info('Access for IP:%s allowed' % (ip_addr)) |
|
153 | log.info('Access for IP:%s allowed' % (ip_addr)) |
@@ -536,6 +536,7 b' class UserIpMap(Base, BaseModel):' | |||||
536 | ip_id = Column("ip_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) |
|
536 | ip_id = Column("ip_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) | |
537 | user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None) |
|
537 | user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None) | |
538 | ip_addr = Column("ip_addr", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None) |
|
538 | ip_addr = Column("ip_addr", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None) | |
|
539 | active = Column("active", Boolean(), nullable=True, unique=None, default=True) | |||
539 | user = relationship('User', lazy='joined') |
|
540 | user = relationship('User', lazy='joined') | |
540 |
|
541 | |||
541 | @classmethod |
|
542 | @classmethod |
@@ -27,7 +27,6 b' import logging' | |||||
27 | import traceback |
|
27 | import traceback | |
28 | import itertools |
|
28 | import itertools | |
29 | import collections |
|
29 | import collections | |
30 | import functools |
|
|||
31 | from pylons import url |
|
30 | from pylons import url | |
32 | from pylons.i18n.translation import _ |
|
31 | from pylons.i18n.translation import _ | |
33 |
|
32 |
@@ -2002,7 +2002,6 b' a.metatag[tag="license"]:hover {' | |||||
2002 | } |
|
2002 | } | |
2003 |
|
2003 | |||
2004 | #login div.title { |
|
2004 | #login div.title { | |
2005 | width: 420px; |
|
|||
2006 | clear: both; |
|
2005 | clear: both; | |
2007 | overflow: hidden; |
|
2006 | overflow: hidden; | |
2008 | position: relative; |
|
2007 | position: relative; | |
@@ -2021,7 +2020,6 b' a.metatag[tag="license"]:hover {' | |||||
2021 | } |
|
2020 | } | |
2022 |
|
2021 | |||
2023 | #login div.inner { |
|
2022 | #login div.inner { | |
2024 | width: 380px; |
|
|||
2025 | background: #FFF url("../images/login.png") no-repeat top left; |
|
2023 | background: #FFF url("../images/login.png") no-repeat top left; | |
2026 | border-top: none; |
|
2024 | border-top: none; | |
2027 | border-bottom: none; |
|
2025 | border-bottom: none; | |
@@ -2038,7 +2036,6 b' a.metatag[tag="license"]:hover {' | |||||
2038 | } |
|
2036 | } | |
2039 |
|
2037 | |||
2040 | #login div.form div.fields div.field div.input input { |
|
2038 | #login div.form div.fields div.field div.input input { | |
2041 | width: 176px; |
|
|||
2042 | background: #FFF; |
|
2039 | background: #FFF; | |
2043 | border-top: 1px solid #b3b3b3; |
|
2040 | border-top: 1px solid #b3b3b3; | |
2044 | border-left: 1px solid #b3b3b3; |
|
2041 | border-left: 1px solid #b3b3b3; |
General Comments 0
You need to be logged in to leave comments.
Login now