modified file chmod 100755 => 100644
@@ -50,12 +50,14 @@ cache_dir = %(here)s/data
index_dir = %(here)s/data/index
app_instance_uuid = ${app_instance_uuid}
cut_off_limit = 256000
force_https = false
commit_parse_limit = 50
use_gravatar = true
container_auth_enabled = false
proxypass_auth_enabled = false
####################################
### CELERY CONFIG ####
use_celery = false
broker.host = localhost
@@ -220,58 +220,109 @@ def authenticate(username, password):
pass
except (Exception,):
log.error(traceback.format_exc())
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
log.info('User %s was created by container authentication', username)
if not user.active:
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):
"""
A simple object that handles all attributes of user in RhodeCode
It does lookup based on API key,given user, or user present in session
Then it fills all required information for such user. It also checks if
anonymous access is enabled and if so, it returns default user as logged
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 = ''
self.is_authenticated = False
self.admin = False
self.permissions = {}
self._api_key = api_key
self.propagate_data()
def propagate_data(self):
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 \
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
self.user_id = None
self.username = None
if not self.username:
log.debug('Auth User is now %s', self)
user_model.fill_perms(self)
@property
def is_admin(self):
@@ -5,15 +5,16 @@ Provides the BaseController class for su
import logging
import time
from pylons import config, tmpl_context as c, request, session, url
from pylons.controllers import WSGIController
from pylons.controllers.util import redirect
from pylons.templating import render_mako as render
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
from rhodecode import BACKENDS
from rhodecode.model.db import Repository
@@ -41,14 +42,21 @@ class BaseController(WSGIController):
# available in environ['pylons.routes_dict']
start = time.time()
try:
# 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)
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:
getattr(session.get('rhodecode_user'),
'is_authenticated', False))
session['rhodecode_user'] = self.rhodecode_user
session.save()
return WSGIController.__call__(self, environ, start_response)
finally:
@@ -452,13 +452,14 @@ HasRepoPermissionAny, HasRepoPermissionA
#==============================================================================
# GRAVATAR URL
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 \
return url("/images/user%s.png" % size)
ssl_enabled = 'https' == request.environ.get('wsgi.url_scheme')
default = 'identicon'
baseurl_nossl = "http://www.gravatar.com/avatar/"
baseurl_ssl = "https://secure.gravatar.com/avatar/"
@@ -67,13 +67,13 @@ from dulwich.repo import Repo
from dulwich.web import HTTPGitApplication
from paste.auth.basic import AuthBasicAuthenticator
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
from webob.exc import HTTPNotFound, HTTPForbidden, HTTPInternalServerError
log = logging.getLogger(__name__)
@@ -145,13 +145,13 @@ class SimpleGit(object):
'authentication')
#==============================================================
# DEFAULT PERM FAILED OR ANONYMOUS ACCESS IS DISABLED SO WE
# 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)
if isinstance(result, str):
AUTH_TYPE.update(environ, 'basic')
REMOTE_USER.update(environ, result)
@@ -161,16 +161,16 @@ class SimpleGit(object):
# CHECK PERMISSIONS FOR THIS REQUEST USING GIVEN USERNAME FROM
# BASIC AUTH
if action in ['pull', 'push']:
username = get_container_username(environ, self.config)
user = self.__get_user(username)
if user is None or not user.active:
return HTTPForbidden()(environ, start_response)
username = user.username
except:
return HTTPInternalServerError()(environ,
start_response)
@@ -32,13 +32,13 @@ from mercurial.error import RepoError
from mercurial.hgweb import hgweb_mod
from rhodecode.lib.utils import make_ui, invalidate_cache, \
is_valid_repo, ui_sections
@@ -111,13 +111,13 @@ class SimpleHg(object):
@@ -127,16 +127,16 @@ class SimpleHg(object):
@@ -89,12 +89,41 @@ class UserModel(BaseModel):
return new_user
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:
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.debug('User %s already exists. Skipping creation of account for container auth.',
username)
def create_ldap(self, username, password, user_dn, attrs):
Checks if user is in database, if not creates this user marked
as ldap user
@@ -240,22 +269,25 @@ class UserModel(BaseModel):
if api_key:
dbuser = self.get_by_api_key(api_key)
dbuser = self.get(user_id)
if dbuser is not None and dbuser.active:
log.debug('filling %s data', dbuser)
setattr(auth_user, k, v)
auth_user.is_authenticated = False
return auth_user
def fill_perms(self, user):
Fills user permission attribute with permissions taken from database
works for permissions given for repositories, and for permissions that
are granted to groups
Status change: