@@ -57,11 +57,12 @@ class PermissionsController(BaseControll
('repository.write', _('Write'),),
('repository.admin', _('Admin'),)]
self.register_choices = [
('hg.register.none', 'disabled'),
('hg.register.none',
_('disabled')),
('hg.register.manual_activate',
_('allowed with manual account activation')),
('hg.register.auto_activate',
_('allowed with automatic account activation')), ]
self.create_choices = [('hg.create.none', _('Disabled')),
('hg.create.repository', _('Enabled'))]
@@ -142,8 +143,10 @@ class PermissionsController(BaseControll
c.create_choices = self.create_choices
if id == 'default':
defaults = {'_method':'put'}
for p in UserModel().get_by_username('default').user_perms:
default_user = UserModel().get_by_username('default')
defaults = {'_method':'put',
'anonymous':default_user.active}
for p in default_user.user_perms:
if p.permission.permission_name.startswith('repository.'):
defaults['default_perm'] = p.permission.permission_name
@@ -121,11 +121,15 @@ class SettingsController(BaseController)
try:
hgsettings1 = self.sa.query(RhodeCodeSettings)\
.filter(RhodeCodeSettings.app_settings_name == 'title').one()
.filter(RhodeCodeSettings.app_settings_name \
== 'title').one()
hgsettings1.app_settings_value = form_result['rhodecode_title']
hgsettings2 = self.sa.query(RhodeCodeSettings)\
.filter(RhodeCodeSettings.app_settings_name == 'realm').one()
== 'realm').one()
hgsettings2.app_settings_value = form_result['rhodecode_realm']
@@ -45,26 +45,26 @@ class UsersController(BaseController):
# To properly map this controller, ensure your config/routing.py
# file has a resource setup:
# map.resource('user', 'users')
@LoginRequired()
@HasPermissionAllDecorator('hg.admin')
def __before__(self):
c.admin_user = session.get('admin_user')
c.admin_username = session.get('admin_username')
super(UsersController, self).__before__()
def index(self, format='html'):
"""GET /users: All items in the collection"""
# url('users')
c.users_list = self.sa.query(User).all()
return render('admin/users/users.html')
def create(self):
"""POST /users: Create a new item"""
user_model = UserModel()
login_form = UserForm()()
@@ -79,13 +79,13 @@ class UsersController(BaseController):
defaults=errors.value,
errors=errors.error_dict or {},
prefix_error=False,
encoding="UTF-8")
except Exception:
log.error(traceback.format_exc())
h.flash(_('error occured during creation of user %s') \
% request.POST.get('username'), category='error')
return redirect(url('users'))
def new(self, format='html'):
"""GET /users/new: Form to create a new item"""
# url('new_user')
@@ -101,7 +101,7 @@ class UsersController(BaseController):
# url('user', id=ID)
c.user = user_model.get(id)
_form = UserForm(edit=True, old_data={'user_id':id,
'email':c.user.email})()
form_result = {}
@@ -109,21 +109,21 @@ class UsersController(BaseController):
form_result = _form.to_python(dict(request.POST))
user_model.update(id, form_result)
h.flash(_('User updated succesfully'), category='success')
except formencode.Invalid, errors:
return htmlfill.render(
render('admin/users/user_edit.html'),
h.flash(_('error occured during update of user %s') \
% form_result.get('username'), category='error')
def delete(self, id):
"""DELETE /users/id: Delete an existing item"""
# Forms posted to this method should contain a hidden field:
@@ -140,14 +140,14 @@ class UsersController(BaseController):
h.flash(str(e), category='warning')
h.flash(_('An error occured during deletion of user'),
category='error')
def show(self, id, format='html'):
"""GET /users/id: Show a specific item"""
def edit(self, id, format='html'):
"""GET /users/id/edit: Form to edit an existing item"""
# url('edit_user', id=ID)
@@ -155,14 +155,13 @@ class UsersController(BaseController):
if not c.user:
if c.user.username == 'default':
h.flash(_("You can't edit this user since it's"
" crucial for entire application"), category='warning')
h.flash(_("You can't edit this user"), category='warning')
defaults = c.user.__dict__
defaults=defaults,
encoding="UTF-8",
force_defaults=False
)
@@ -46,7 +46,9 @@ class LoginController(BaseController):
#redirect if already logged in
c.came_from = request.GET.get('came_from', None)
if c.rhodecode_user.is_authenticated:
if c.rhodecode_user.is_authenticated \
and c.rhodecode_user.username != 'default':
return redirect(url('home'))
if request.POST:
@@ -26,15 +26,16 @@ from pylons import config, session, url,
from pylons.controllers.util import abort, redirect
from rhodecode.lib.utils import get_repo_slug
from rhodecode.model import meta
from rhodecode.model.user import UserModel
from rhodecode.model.caching_query import FromCache
from rhodecode.model.db import User, RepoToPerm, Repository, Permission, \
UserToPerm
import bcrypt
from decorator import decorator
import logging
import random
log = logging.getLogger(__name__)
class PasswordGenerator(object):
"""This is a simple class for generating password from
@@ -53,7 +54,7 @@ class PasswordGenerator(object):
ALPHABETS_BIG_SMALL = ALPHABETS_BIG + ALPHABETS_SMALL
ALPHABETS_ALPHANUM_BIG = ALPHABETS_BIG + ALPHABETS_NUM#[6]
ALPHABETS_ALPHANUM_SMALL = ALPHABETS_SMALL + ALPHABETS_NUM#[7]
def __init__(self, passwd=''):
self.passwd = passwd
@@ -61,20 +62,19 @@ class PasswordGenerator(object):
self.passwd = ''.join([random.choice(type) for _ in xrange(len)])
return self.passwd
def get_crypt_password(password):
"""Cryptographic function used for password hashing based on sha1
:param password: password to hash
"""
return bcrypt.hashpw(password, bcrypt.gensalt(10))
def check_password(password, hashed):
return bcrypt.hashpw(password, hashed) == hashed
def authfunc(environ, username, password):
user = UserModel().get_by_username(username, cache=False)
if user:
if user.active:
if user.username == username and check_password(password, user.password):
@@ -82,7 +82,7 @@ def authfunc(environ, username, password
return True
else:
log.error('user %s is disabled', username)
return False
class AuthUser(object):
@@ -99,6 +99,8 @@ class AuthUser(object):
self.is_admin = False
self.permissions = {}
def __repr__(self):
return "<AuthUser('id:%s:%s')>" % (self.user_id, self.username)
def set_available_permissions(config):
@@ -116,85 +118,56 @@ def set_available_permissions(config):
pass
finally:
meta.Session.remove()
config['available_permissions'] = [x.permission_name for x in all_perms]
def set_base_path(config):
config['base_path'] = config['pylons.app_globals'].base_path
def fill_data(user):
Fills user data with those from database and log out user if not present
in database
:param user:
sa = meta.Session()
dbuser = sa.query(User)\
.options(FromCache('sql_cache_short', 'getuser_%s' % user.user_id))\
.get(user.user_id)
except:
if dbuser:
user.username = dbuser.username
user.is_admin = dbuser.admin
user.name = dbuser.name
user.lastname = dbuser.lastname
user.email = dbuser.email
user.is_authenticated = False
return user
def fill_perms(user):
Fills user permission attribute with permissions taken from database
user.permissions['repositories'] = {}
user.permissions['global'] = set()
#===========================================================================
# fetch default permissions
default_user = sa.query(User)\
.options(FromCache('sql_cache_short', 'getuser_%s' % 'default'))\
.filter(User.username == 'default').scalar()
default_user = UserModel(sa).get_by_username('default', cache=True)
default_perms = sa.query(RepoToPerm, Repository, Permission)\
.join((Repository, RepoToPerm.repository_id == Repository.repo_id))\
.join((Permission, RepoToPerm.permission_id == Permission.permission_id))\
.filter(RepoToPerm.user == default_user).all()
if user.is_admin:
#=======================================================================
# #admin have all default rights set to admin
user.permissions['global'].add('hg.admin')
for perm in default_perms:
p = 'repository.admin'
user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
# set default permissions
#default global
default_global_perms = sa.query(UserToPerm)\
.filter(UserToPerm.user == sa.query(User).filter(User.username ==
'default').one())
for perm in default_global_perms:
user.permissions['global'].add(perm.permission.permission_name)
#default repositories
if perm.Repository.private and not perm.Repository.user_id == user.user_id:
@@ -205,9 +178,9 @@ def fill_perms(user):
p = perm.Permission.permission_name
# #overwrite default with user permissions if any
@@ -215,38 +188,52 @@ def fill_perms(user):
.filter(RepoToPerm.user_id == user.user_id).all()
for perm in user_perms:
if perm.Repository.user_id == user.user_id:#set admin if owner
def get_user(session):
Gets user from session, and wraps permissions into user
:param session:
user = session.get('rhodecode_user', AuthUser())
#if the user is not logged in we check for anonymous access
#if user is logged and it's a default user check if we still have anonymous
#access enabled
if user.user_id is None or user.username == 'default':
anonymous_user = UserModel().get_by_username('default', cache=True)
if anonymous_user.active is True:
#then we set this user is logged in
user.is_authenticated = True
if user.is_authenticated:
user = fill_data(user)
user = UserModel().fill_data(user)
user = fill_perms(user)
session['rhodecode_user'] = user
session.save()
#===============================================================================
# CHECK DECORATORS
class LoginRequired(object):
"""Must be logged in to execute this function else redirect to login page"""
def __call__(self, func):
return decorator(self.__wrapper, func)
def __wrapper(self, func, *fargs, **fkwargs):
log.debug('Checking login required for user:%s', user.username)
@@ -255,21 +242,21 @@ class LoginRequired(object):
return func(*fargs, **fkwargs)
log.warn('user %s not authenticated', user.username)
p = ''
if request.environ.get('SCRIPT_NAME') != '/':
p += request.environ.get('SCRIPT_NAME')
p += request.environ.get('PATH_INFO')
if request.environ.get('QUERY_STRING'):
p += '?' + request.environ.get('QUERY_STRING')
log.debug('redirecting to login page with %s', p)
return redirect(url('login_home', came_from=p))
class PermsDecorator(object):
"""Base class for decorators"""
def __init__(self, *required_perms):
available_perms = config['available_permissions']
for perm in required_perms:
@@ -277,32 +264,33 @@ class PermsDecorator(object):
raise Exception("'%s' permission is not defined" % perm)
self.required_perms = set(required_perms)
self.user_perms = None
# _wrapper.__name__ = func.__name__
# _wrapper.__dict__.update(func.__dict__)
# _wrapper.__doc__ = func.__doc__
self.user = session.get('rhodecode_user', AuthUser())
self.user_perms = self.user.permissions
log.debug('checking %s permissions %s for %s %s',
self.__class__.__name__, self.required_perms, func.__name__,
self.user)
self.user_perms = session.get('rhodecode_user', AuthUser()).permissions
log.debug('checking %s permissions %s for %s',
self.__class__.__name__, self.required_perms, func.__name__)
if self.check_permissions():
log.debug('Permission granted for %s', func.__name__)
log.debug('Permission granted for %s %s', func.__name__, self.user)
log.warning('Permission denied for %s', func.__name__)
log.warning('Permission denied for %s %s', func.__name__, self.user)
#redirect with forbidden ret code
return abort(403)
def check_permissions(self):
"""Dummy function for overriding"""
raise Exception('You have to write this function in child class')
@@ -311,18 +299,18 @@ class HasPermissionAllDecorator(PermsDec
"""Checks for access permission for all given predicates. All of them
have to be meet in order to fulfill the request
if self.required_perms.issubset(self.user_perms.get('global')):
class HasPermissionAnyDecorator(PermsDecorator):
"""Checks for access permission for any of given predicates. In order to
fulfill the request any of predicates must be meet
if self.required_perms.intersection(self.user_perms.get('global')):
@@ -332,7 +320,7 @@ class HasRepoPermissionAllDecorator(Perm
"""Checks for access permission for all given predicates for specific
repository. All of them have to be meet in order to fulfill the request
repo_name = get_repo_slug(request)
@@ -342,16 +330,16 @@ class HasRepoPermissionAllDecorator(Perm
if self.required_perms.issubset(user_perms):
class HasRepoPermissionAnyDecorator(PermsDecorator):
"""Checks for access permission for any of given predicates for specific
repository. In order to fulfill the request any of predicates must be meet
user_perms = set([self.user_perms['repositories'][repo_name]])
except KeyError:
@@ -365,10 +353,10 @@ class HasRepoPermissionAnyDecorator(Perm
class PermsFunction(object):
"""Base function for other check functions"""
def __init__(self, *perms):
for perm in perms:
if perm not in available_perms:
raise Exception("'%s' permission in not defined" % perm)
@@ -376,29 +364,30 @@ class PermsFunction(object):
self.granted_for = ''
self.repo_name = None
def __call__(self, check_Location=''):
user = session.get('rhodecode_user', False)
if not user:
self.user_perms = user.permissions
self.granted_for = user.username
log.debug('checking %s %s', self.__class__.__name__, self.required_perms)
log.debug('checking %s %s %s', self.__class__.__name__,
self.required_perms, user)
log.debug('Permission granted for %s @%s', self.granted_for,
check_Location)
log.debug('Permission granted for %s @ %s %s', self.granted_for,
check_Location, user)
log.warning('Permission denied for %s @%s', self.granted_for,
log.warning('Permission denied for %s @ %s %s', self.granted_for,
class HasPermissionAll(PermsFunction):
@@ -412,11 +401,11 @@ class HasPermissionAny(PermsFunction):
class HasRepoPermissionAll(PermsFunction):
def __call__(self, repo_name=None, check_Location=''):
self.repo_name = repo_name
return super(HasRepoPermissionAll, self).__call__(check_Location)
if not self.repo_name:
self.repo_name = get_repo_slug(request)
@@ -426,17 +415,17 @@ class HasRepoPermissionAll(PermsFunction
[self.repo_name]])
self.granted_for = self.repo_name
if self.required_perms.issubset(self.user_perms):
class HasRepoPermissionAny(PermsFunction):
return super(HasRepoPermissionAny, self).__call__(check_Location)
@@ -458,13 +447,13 @@ class HasRepoPermissionAny(PermsFunction
class HasPermissionAnyMiddleware(object):
self.required_perms = set(perms)
def __call__(self, user, repo_name):
usr = AuthUser()
usr.user_id = user.user_id
usr.username = user.username
usr.is_admin = user.admin
self.user_perms = set([fill_perms(usr)\
.permissions['repositories'][repo_name]])
@@ -472,9 +461,9 @@ class HasPermissionAnyMiddleware(object)
self.user_perms = set()
self.username = user.username
return self.check_permissions()
log.debug('checking mercurial protocol '
'permissions for user:%s repository:%s',
@@ -138,17 +138,17 @@ class DbManage(object):
hooks2.ui_section = 'hooks'
hooks2.ui_key = 'changegroup.repo_size'
hooks2.ui_value = 'python:rhodecode.lib.hooks.repo_size'
hooks3 = RhodeCodeUi()
hooks3.ui_section = 'hooks'
hooks3.ui_key = 'pretxnchangegroup.push_logger'
hooks3.ui_value = 'python:rhodecode.lib.hooks.log_push_action'
hooks4 = RhodeCodeUi()
hooks4.ui_section = 'hooks'
hooks4.ui_key = 'preoutgoing.pull_logger'
hooks4.ui_value = 'python:rhodecode.lib.hooks.log_pull_action'
web1 = RhodeCodeUi()
web1.ui_section = 'web'
@@ -227,9 +227,9 @@ class DbManage(object):
def_user = User()
def_user.username = 'default'
def_user.password = get_crypt_password(str(uuid.uuid1())[:8])
def_user.name = 'default'
def_user.lastname = 'default'
def_user.email = 'default@default.com'
def_user.name = 'Anonymous'
def_user.lastname = 'User'
def_user.email = 'anonymous@rhodecode.org'
def_user.admin = False
def_user.active = False
@@ -358,6 +358,7 @@ def DefaultPermissionsForm(perms_choices
allow_extra_fields = True
filter_extra_fields = True
overwrite_default = OneOf(['true', 'false'], if_missing='false')
anonymous = OneOf(['True', 'False'], if_missing=False)
default_perm = OneOf(perms_choices)
default_register = OneOf(register_choices)
default_create = OneOf(create_choices)
@@ -59,30 +59,41 @@ class PermissionModel(object):
.filter(User.username == form_result['perm_user_name']).scalar()
u2p = self.sa.query(UserToPerm).filter(UserToPerm.user == perm_user).all()
if len(u2p) != 3:
raise Exception('There is more than 3 defined'
' permissions for default user. This should not happen please verify'
' your database')
raise Exception('Defined: %s should be 3 permissions for default'
' user. This should not happen please verify'
' your database' % len(u2p))
#stage 1 change defaults
for p in u2p:
p.permission = self.get_permission_by_name(form_result['default_perm'])
p.permission = self.get_permission_by_name(
form_result['default_perm'])
self.sa.add(p)
if p.permission.permission_name.startswith('hg.register.'):
p.permission = self.get_permission_by_name(form_result['default_register'])
form_result['default_register'])
if p.permission.permission_name.startswith('hg.create.'):
p.permission = self.get_permission_by_name(form_result['default_create'])
form_result['default_create'])
#stage 2 update all default permissions for repos if checked
if form_result['overwrite_default'] == 'true':
for r2p in self.sa.query(RepoToPerm).filter(RepoToPerm.user == perm_user).all():
r2p.permission = self.get_permission_by_name(form_result['default_perm'])
for r2p in self.sa.query(RepoToPerm)\
.filter(RepoToPerm.user == perm_user).all():
r2p.permission = self.get_permission_by_name(
self.sa.add(r2p)
#stage 3 set anonymous access
if perm_user.username == 'default':
perm_user.active = bool(form_result['anonymous'])
self.sa.add(perm_user)
self.sa.commit()
@@ -143,3 +143,24 @@ class UserModel(object):
def reset_password(self, data):
from rhodecode.lib.celerylib import tasks, run_task
run_task(tasks.reset_user_password, data['email'])
def fill_data(self, user):
Fills user data with those from database and log out user if not
present in database
log.debug('filling auth user data')
dbuser = self.get(user.user_id)
@@ -2096,7 +2096,7 @@ border:1px solid #666;
clear:both;
overflow:hidden;
margin:0;
padding:2px 0;
padding:2px 2px;
}
#content div.box div.form div.fields div.field div.checkboxes div.checkbox input,#content div.box div.form div.fields div.field div.radios div.radio input {
@@ -26,7 +26,16 @@
<div class="form">
<!-- fields -->
<div class="fields">
<div class="field">
<div class="label label-checkbox">
<label for="anonymous">${_('Anonymous access')}:</label>
</div>
<div class="checkboxes">
<div class="checkbox">
${h.checkbox('anonymous',True)}
<div class="label">
<label for="default_perm">${_('Repository permission')}:</label>
@@ -20,12 +20,22 @@
<div class="gravatar">
<img alt="gravatar" src="${h.gravatar_url(c.rhodecode_user.email,24)}" />
%if c.rhodecode_user.username == 'default':
<div class="account">
${h.link_to('%s %s'%(c.rhodecode_user.name,c.rhodecode_user.lastname),h.url('#'))}<br/>
${h.link_to(c.rhodecode_user.username,h.url('#'))}
</li>
<li class="last highlight">${h.link_to(u'Login',h.url('login_home'))}</li>
%else:
${h.link_to('%s %s'%(c.rhodecode_user.name,c.rhodecode_user.lastname),h.url('admin_settings_my_account'))}<br/>
${h.link_to(c.rhodecode_user.username,h.url('admin_settings_my_account'))}
<li class="last highlight">${h.link_to(u'Logout',h.url('logout_home'))}</li>
%endif
</ul>
<!-- end user -->
<div id="header-inner" class="title top-left-rounded-corner top-right-rounded-corner">
Status change: