modified file chmod 100755 => 100644
@@ -44,24 +44,26 @@ port = 5000
[app:main]
use = egg:rhodecode
full_stack = true
static_files = true
lang=en
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
broker.vhost = rabbitmqhost
broker.port = 5672
broker.user = rabbitmq
broker.password = qweqwe
celery.imports = rhodecode.lib.celerylib.tasks
@@ -214,70 +214,121 @@ def authenticate(username, password):
if user_model.create_ldap(username, password, user_dn,
user_attrs):
log.info('created new ldap user %s', username)
return True
except (LdapUsernameError, LdapPasswordError,):
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):
return self.admin
def full_contact(self):
return '%s %s <%s>' % (self.name, self.lastname, self.email)
"""The base Controller API
Provides the BaseController class for subclassing.
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
log = logging.getLogger(__name__)
class BaseController(WSGIController):
def __before__(self):
c.rhodecode_version = __version__
@@ -35,26 +36,33 @@ class BaseController(WSGIController):
#c.unread_journal = scm_model.get_unread_journal()
def __call__(self, environ, start_response):
"""Invoke the Controller"""
# WSGIController.__call__ dispatches to the Controller method
# the request is routed to. This routing information is
# 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:
log.debug('Request time: %.3fs' % (time.time()-start))
meta.Session.remove()
class BaseRepoController(BaseController):
@@ -446,25 +446,26 @@ def action_parser_icon(user_log):
#==============================================================================
# PERMS
from rhodecode.lib.auth import HasPermissionAny, HasPermissionAll, \
HasRepoPermissionAny, HasRepoPermissionAll
# 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/"
baseurl = baseurl_ssl if ssl_enabled else baseurl_nossl
if isinstance(email_address, unicode):
#hashlib crashes on unicode items
email_address = safe_str(email_address)
# construct the url
@@ -61,25 +61,25 @@ class SimpleGitUploadPackHandler(dulserv
dulserver.DEFAULT_HANDLERS = {
'git-upload-pack': SimpleGitUploadPackHandler,
'git-receive-pack': dulserver.ReceivePackHandler,
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
def is_git(environ):
"""Returns True if request's target is git server.
``HTTP_USER_AGENT`` would then have git client version given.
@@ -139,44 +139,44 @@ class SimpleGit(object):
if anonymous_perm is not True or anonymous_user.active is False:
if anonymous_perm is not True:
log.debug('Not enough credentials to access this '
'repository as anonymous user')
if anonymous_user.active is False:
log.debug('Anonymous access is disabled, running '
'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)
return result.wsgi_application(environ, start_response)
# 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)
#check permissions for this repository
perm = self.__check_permission(action, user,
repo_name)
if perm is not True:
@@ -26,25 +26,25 @@
import os
import traceback
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
def is_mercurial(environ):
"""Returns True if request's target is mercurial server - header
``HTTP_ACCEPT`` of such request would start with ``application/mercurial``.
@@ -105,44 +105,44 @@ class SimpleHg(object):
@@ -83,24 +83,53 @@ class UserModel(BaseModel):
for k, v in form_data.items():
setattr(new_user, k, v)
new_user.api_key = generate_api_key(form_data['username'])
self.sa.add(new_user)
self.sa.commit()
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']
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
:param password:
:param user_dn:
from rhodecode.lib.auth import get_crypt_password
log.debug('Checking for such ldap account in RhodeCode database')
@@ -234,34 +263,37 @@ class UserModel(BaseModel):
:param user_id: user id to fetch by
:param api_key: api key to fetch by
if user_id is None and api_key is None:
raise Exception('You need to pass user_id or api_key')
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
:param user: user instance to fill his perms
user.permissions['repositories'] = {}
user.permissions['global'] = set()
Status change: