# HG changeset patch # User Liad Shani # Date 1319909203 -7200 # Node ID d58e514c0a3901b4f1dcdd3b5313b68b372943fa # Parent cbc2b1913cdfc5522f38bb4e0b558ba4f934923f# Parent 2755c11c90d8f4adee98fcd42b9053324cd8abc6 Merge with upstream diff -r 2755c11c90d8 -r d58e514c0a39 init.d/rhodecode-daemon3 diff -r 2755c11c90d8 -r d58e514c0a39 rhodecode/config/deployment.ini_tmpl --- a/rhodecode/config/deployment.ini_tmpl Sat Oct 29 17:44:46 2011 +0200 +++ b/rhodecode/config/deployment.ini_tmpl Sat Oct 29 19:26:43 2011 +0200 @@ -53,6 +53,8 @@ force_https = false commit_parse_limit = 50 use_gravatar = true +container_auth_enabled = false +proxypass_auth_enabled = false #################################### ### CELERY CONFIG #### diff -r 2755c11c90d8 -r d58e514c0a39 rhodecode/lib/auth.py --- a/rhodecode/lib/auth.py Sat Oct 29 17:44:46 2011 +0200 +++ b/rhodecode/lib/auth.py Sat Oct 29 19:26:43 2011 +0200 @@ -223,6 +223,43 @@ pass return False +def login_container_auth(username): + user = User.get_by_username(username) + if user is None: + user_model = UserModel() + user_attrs = { + 'name': username, + 'lastname': None, + 'email': None, + } + if not user_model.create_for_container_auth(username, user_attrs): + return None + user = User.get_by_username(username) + log.info('User %s was created by container authentication', username) + + if not user.active: + return None + + user.update_lastlogin() + log.debug('User %s is now logged in by container authentication', user.username) + return user + +def get_container_username(environ, cfg=config): + from paste.httpheaders import REMOTE_USER + from paste.deploy.converters import asbool + + username = REMOTE_USER(environ) + + if not username and asbool(cfg.get('proxypass_auth_enabled', False)): + username = environ.get('HTTP_X_FORWARDED_USER') + + if username: + #Removing realm and domain from username + username = username.partition('@')[0] + username = username.rpartition('\\')[2] + log.debug('Received username %s from container', username) + + return username class AuthUser(object): """ @@ -234,12 +271,12 @@ in """ - def __init__(self, user_id=None, api_key=None): + def __init__(self, user_id=None, api_key=None, username=None): self.user_id = user_id self.api_key = None - - self.username = 'None' + self.username = username + self.name = '' self.lastname = '' self.email = '' @@ -252,23 +289,37 @@ def propagate_data(self): user_model = UserModel() self.anonymous_user = User.get_by_username('default') + is_user_loaded = False if self._api_key and self._api_key != self.anonymous_user.api_key: #try go get user by api key log.debug('Auth User lookup by API KEY %s', self._api_key) - user_model.fill_data(self, api_key=self._api_key) - else: + is_user_loaded = user_model.fill_data(self, api_key=self._api_key) + elif self.user_id is not None \ + and self.user_id != self.anonymous_user.user_id: log.debug('Auth User lookup by USER ID %s', self.user_id) - if self.user_id is not None \ - and self.user_id != self.anonymous_user.user_id: - user_model.fill_data(self, user_id=self.user_id) + is_user_loaded = user_model.fill_data(self, user_id=self.user_id) + elif self.username: + log.debug('Auth User lookup by USER NAME %s', self.username) + dbuser = login_container_auth(self.username) + if dbuser is not None: + for k, v in dbuser.get_dict().items(): + setattr(self, k, v) + self.set_authenticated() + is_user_loaded = True + + if not is_user_loaded: + if self.anonymous_user.active is True: + user_model.fill_data(self, + user_id=self.anonymous_user.user_id) + #then we set this user is logged in + self.is_authenticated = True else: - if self.anonymous_user.active is True: - user_model.fill_data(self, - user_id=self.anonymous_user.user_id) - #then we set this user is logged in - self.is_authenticated = True - else: - self.is_authenticated = False + self.user_id = None + self.username = None + self.is_authenticated = False + + if not self.username: + self.username = 'None' log.debug('Auth User is now %s', self) user_model.fill_perms(self) diff -r 2755c11c90d8 -r d58e514c0a39 rhodecode/lib/base.py --- a/rhodecode/lib/base.py Sat Oct 29 17:44:46 2011 +0200 +++ b/rhodecode/lib/base.py Sat Oct 29 19:26:43 2011 +0200 @@ -8,9 +8,10 @@ from pylons.controllers import WSGIController from pylons.controllers.util import redirect from pylons.templating import render_mako as render +from paste.deploy.converters import asbool from rhodecode import __version__ -from rhodecode.lib.auth import AuthUser +from rhodecode.lib.auth import AuthUser, get_container_username from rhodecode.lib.utils import get_repo_slug from rhodecode.model import meta from rhodecode.model.scm import ScmModel @@ -44,8 +45,15 @@ # putting this here makes sure that we update permissions each time api_key = request.GET.get('api_key') user_id = getattr(session.get('rhodecode_user'), 'user_id', None) - self.rhodecode_user = c.rhodecode_user = AuthUser(user_id, api_key) - self.rhodecode_user.set_authenticated( + if asbool(config.get('container_auth_enabled', False)): + username = get_container_username(environ) + else: + username = None + + self.rhodecode_user = c.rhodecode_user = AuthUser(user_id, api_key, username) + if not self.rhodecode_user.is_authenticated and \ + self.rhodecode_user.user_id is not None: + self.rhodecode_user.set_authenticated( getattr(session.get('rhodecode_user'), 'is_authenticated', False)) session['rhodecode_user'] = self.rhodecode_user diff -r 2755c11c90d8 -r d58e514c0a39 rhodecode/lib/helpers.py --- a/rhodecode/lib/helpers.py Sat Oct 29 17:44:46 2011 +0200 +++ b/rhodecode/lib/helpers.py Sat Oct 29 19:26:43 2011 +0200 @@ -455,7 +455,8 @@ def gravatar_url(email_address, size=30): if not str2bool(config['app_conf'].get('use_gravatar')) or \ - email_address == 'anonymous@rhodecode.org': + not email_address or \ + email_address == 'anonymous@rhodecode.org': return url("/images/user%s.png" % size) ssl_enabled = 'https' == request.environ.get('wsgi.url_scheme') diff -r 2755c11c90d8 -r d58e514c0a39 rhodecode/lib/middleware/simplegit.py --- a/rhodecode/lib/middleware/simplegit.py Sat Oct 29 17:44:46 2011 +0200 +++ b/rhodecode/lib/middleware/simplegit.py Sat Oct 29 19:26:43 2011 +0200 @@ -70,7 +70,7 @@ from paste.httpheaders import REMOTE_USER, AUTH_TYPE from rhodecode.lib import safe_str -from rhodecode.lib.auth import authfunc, HasPermissionAnyMiddleware +from rhodecode.lib.auth import authfunc, HasPermissionAnyMiddleware, get_container_username from rhodecode.lib.utils import invalidate_cache, is_valid_repo from rhodecode.model.db import User @@ -148,7 +148,7 @@ # NEED TO AUTHENTICATE AND ASK FOR AUTH USER PERMISSIONS #============================================================== - if not REMOTE_USER(environ): + if not get_container_username(environ, self.config): self.authenticate.realm = \ safe_str(self.config['rhodecode_realm']) result = self.authenticate(environ) @@ -164,10 +164,10 @@ #============================================================== if action in ['pull', 'push']: - username = REMOTE_USER(environ) + username = get_container_username(environ, self.config) try: user = self.__get_user(username) - if user is None: + if user is None or not user.active: return HTTPForbidden()(environ, start_response) username = user.username except: diff -r 2755c11c90d8 -r d58e514c0a39 rhodecode/lib/middleware/simplehg.py --- a/rhodecode/lib/middleware/simplehg.py Sat Oct 29 17:44:46 2011 +0200 +++ b/rhodecode/lib/middleware/simplehg.py Sat Oct 29 19:26:43 2011 +0200 @@ -35,7 +35,7 @@ from paste.httpheaders import REMOTE_USER, AUTH_TYPE from rhodecode.lib import safe_str -from rhodecode.lib.auth import authfunc, HasPermissionAnyMiddleware +from rhodecode.lib.auth import authfunc, HasPermissionAnyMiddleware, get_container_username from rhodecode.lib.utils import make_ui, invalidate_cache, \ is_valid_repo, ui_sections from rhodecode.model.db import User @@ -114,7 +114,7 @@ # NEED TO AUTHENTICATE AND ASK FOR AUTH USER PERMISSIONS #============================================================== - if not REMOTE_USER(environ): + if not get_container_username(environ, self.config): self.authenticate.realm = \ safe_str(self.config['rhodecode_realm']) result = self.authenticate(environ) @@ -130,10 +130,10 @@ #============================================================== if action in ['pull', 'push']: - username = REMOTE_USER(environ) + username = get_container_username(environ, self.config) try: user = self.__get_user(username) - if user is None: + if user is None or not user.active: return HTTPForbidden()(environ, start_response) username = user.username except: diff -r 2755c11c90d8 -r d58e514c0a39 rhodecode/model/repo.py diff -r 2755c11c90d8 -r d58e514c0a39 rhodecode/model/user.py --- a/rhodecode/model/user.py Sat Oct 29 17:44:46 2011 +0200 +++ b/rhodecode/model/user.py Sat Oct 29 19:26:43 2011 +0200 @@ -92,6 +92,35 @@ self.sa.rollback() raise + def create_for_container_auth(self, username, attrs): + """ + Creates the given user if it's not already in the database + + :param username: + :param attrs: + """ + if self.get_by_username(username, case_insensitive=True) is None: + try: + new_user = User() + new_user.username = username + new_user.password = None + new_user.api_key = generate_api_key(username) + new_user.email = attrs['email'] + new_user.active = True + new_user.name = attrs['name'] + new_user.lastname = attrs['lastname'] + + self.sa.add(new_user) + self.sa.commit() + return True + except (DatabaseError,): + log.error(traceback.format_exc()) + self.sa.rollback() + raise + log.debug('User %s already exists. Skipping creation of account for container auth.', + username) + return False + def create_ldap(self, username, password, user_dn, attrs): """ Checks if user is in database, if not creates this user marked @@ -243,16 +272,19 @@ else: dbuser = self.get(user_id) - if dbuser is not None: + if dbuser is not None and dbuser.active: log.debug('filling %s data', dbuser) for k, v in dbuser.get_dict().items(): setattr(auth_user, k, v) + else: + return False except: log.error(traceback.format_exc()) auth_user.is_authenticated = False + return False - return auth_user + return True def fill_perms(self, user): """ diff -r 2755c11c90d8 -r d58e514c0a39 rhodecode/tests/test_concurency.py