diff --git a/docs/changelog.rst b/docs/changelog.rst --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -37,7 +37,7 @@ news that defines 'default' revision/branch for generating readme files - Implemented #509, RhodeCode enforces SSL for push/pulling if requested. - Import remote svn repositories to mercurial using hgsubversion - +- Fixed #508 RhodeCode now has a option to explicitly set forking permissions fixes +++++ diff --git a/rhodecode/controllers/admin/permissions.py b/rhodecode/controllers/admin/permissions.py --- a/rhodecode/controllers/admin/permissions.py +++ b/rhodecode/controllers/admin/permissions.py @@ -71,6 +71,15 @@ class PermissionsController(BaseControll self.create_choices = [('hg.create.none', _('Disabled')), ('hg.create.repository', _('Enabled'))] + self.fork_choices = [('hg.fork.none', _('Disabled')), + ('hg.fork.repository', _('Enabled'))] + + # set the global template variables + c.perms_choices = self.perms_choices + c.register_choices = self.register_choices + c.create_choices = self.create_choices + c.fork_choices = self.fork_choices + def index(self, format='html'): """GET /permissions: All items in the collection""" # url('permissions') @@ -96,7 +105,8 @@ class PermissionsController(BaseControll _form = DefaultPermissionsForm([x[0] for x in self.perms_choices], [x[0] for x in self.register_choices], - [x[0] for x in self.create_choices])() + [x[0] for x in self.create_choices], + [x[0] for x in self.fork_choices])() try: form_result = _form.to_python(dict(request.POST)) @@ -107,9 +117,6 @@ class PermissionsController(BaseControll category='success') except formencode.Invalid, errors: - c.perms_choices = self.perms_choices - c.register_choices = self.register_choices - c.create_choices = self.create_choices defaults = errors.value return htmlfill.render( @@ -141,10 +148,8 @@ class PermissionsController(BaseControll def edit(self, id, format='html'): """GET /permissions/id/edit: Form to edit an existing item""" #url('edit_permission', id=ID) - c.perms_choices = self.perms_choices - c.register_choices = self.register_choices - c.create_choices = self.create_choices + #this form can only edit default user permissions if id == 'default': default_user = User.get_by_username('default') defaults = {'_method': 'put', @@ -160,10 +165,14 @@ class PermissionsController(BaseControll if p.permission.permission_name.startswith('hg.create.'): defaults['default_create'] = p.permission.permission_name + if p.permission.permission_name.startswith('hg.fork.'): + defaults['default_fork'] = p.permission.permission_name + return htmlfill.render( - render('admin/permissions/permissions.html'), - defaults=defaults, - encoding="UTF-8", - force_defaults=True,) + render('admin/permissions/permissions.html'), + defaults=defaults, + encoding="UTF-8", + force_defaults=True, + ) else: return redirect(url('admin_home')) diff --git a/rhodecode/controllers/admin/users.py b/rhodecode/controllers/admin/users.py --- a/rhodecode/controllers/admin/users.py +++ b/rhodecode/controllers/admin/users.py @@ -33,6 +33,7 @@ from pylons import request, session, tmp from pylons.controllers.util import redirect from pylons.i18n.translation import _ +import rhodecode from rhodecode.lib.exceptions import DefaultUserException, \ UserOwnsReposException from rhodecode.lib import helpers as h @@ -40,14 +41,13 @@ from rhodecode.lib.auth import LoginRequ AuthUser from rhodecode.lib.base import BaseController, render -import rhodecode -from rhodecode.model.db import User, Permission, UserEmailMap +from rhodecode.model.db import User, UserEmailMap from rhodecode.model.forms import UserForm from rhodecode.model.user import UserModel from rhodecode.model.meta import Session from rhodecode.lib.utils import action_logger from rhodecode.lib.compat import json -from rhodecode.lib.utils2 import datetime_to_time +from rhodecode.lib.utils2 import datetime_to_time, str2bool log = logging.getLogger(__name__) @@ -175,9 +175,11 @@ class UsersController(BaseController): .filter(UserEmailMap.user == c.user).all() defaults = errors.value e = errors.error_dict or {} - perm = Permission.get_by_key('hg.create.repository') - defaults.update({'create_repo_perm': user_model.has_perm(id, perm)}) - defaults.update({'_method': 'put'}) + defaults.update({ + 'create_repo_perm': user_model.has_perm(id, 'hg.create.repository'), + 'fork_repo_perm': user_model.has_perm(id, 'hg.fork.repository'), + '_method': 'put' + }) return htmlfill.render( render('admin/users/user_edit.html'), defaults=defaults, @@ -188,7 +190,7 @@ class UsersController(BaseController): log.error(traceback.format_exc()) h.flash(_('error occurred during update of user %s') \ % form_result.get('username'), category='error') - return redirect(url('users')) + return redirect(url('edit_user', id=id)) def delete(self, id): """DELETE /users/id: Delete an existing item""" @@ -198,9 +200,9 @@ class UsersController(BaseController): # h.form(url('delete_user', id=ID), # method='delete') # url('user', id=ID) - user_model = UserModel() + usr = User.get_or_404(id) try: - user_model.delete(id) + UserModel().delete(usr) Session().commit() h.flash(_('successfully deleted user'), category='success') except (UserOwnsReposException, DefaultUserException), e: @@ -223,15 +225,19 @@ class UsersController(BaseController): if c.user.username == 'default': h.flash(_("You can't edit this user"), category='warning') return redirect(url('users')) + c.perm_user = AuthUser(user_id=id) c.user.permissions = {} c.granted_permissions = UserModel().fill_perms(c.user)\ .permissions['global'] c.user_email_map = UserEmailMap.query()\ .filter(UserEmailMap.user == c.user).all() + user_model = UserModel() defaults = c.user.get_dict() - perm = Permission.get_by_key('hg.create.repository') - defaults.update({'create_repo_perm': UserModel().has_perm(id, perm)}) + defaults.update({ + 'create_repo_perm': user_model.has_perm(id, 'hg.create.repository'), + 'fork_repo_perm': user_model.has_perm(id, 'hg.fork.repository'), + }) return htmlfill.render( render('admin/users/user_edit.html'), @@ -243,28 +249,44 @@ class UsersController(BaseController): def update_perm(self, id): """PUT /users_perm/id: Update an existing item""" # url('user_perm', id=ID, method='put') + usr = User.get_or_404(id) + grant_create_perm = str2bool(request.POST.get('create_repo_perm')) + grant_fork_perm = str2bool(request.POST.get('fork_repo_perm')) + inherit_perms = str2bool(request.POST.get('inherit_default_permissions')) - grant_perm = request.POST.get('create_repo_perm', False) user_model = UserModel() - if grant_perm: - perm = Permission.get_by_key('hg.create.none') - user_model.revoke_perm(id, perm) + try: + usr.inherit_default_permissions = inherit_perms + Session().add(usr) - perm = Permission.get_by_key('hg.create.repository') - user_model.grant_perm(id, perm) - h.flash(_("Granted 'repository create' permission to user"), - category='success') + if grant_create_perm: + user_model.revoke_perm(usr, 'hg.create.none') + user_model.grant_perm(usr, 'hg.create.repository') + h.flash(_("Granted 'repository create' permission to user"), + category='success') + else: + user_model.revoke_perm(usr, 'hg.create.repository') + user_model.grant_perm(usr, 'hg.create.none') + h.flash(_("Revoked 'repository create' permission to user"), + category='success') + + if grant_fork_perm: + user_model.revoke_perm(usr, 'hg.fork.none') + user_model.grant_perm(usr, 'hg.fork.repository') + h.flash(_("Granted 'repository fork' permission to user"), + category='success') + else: + user_model.revoke_perm(usr, 'hg.fork.repository') + user_model.grant_perm(usr, 'hg.fork.none') + h.flash(_("Revoked 'repository fork' permission to user"), + category='success') + Session().commit() - else: - perm = Permission.get_by_key('hg.create.repository') - user_model.revoke_perm(id, perm) - - perm = Permission.get_by_key('hg.create.none') - user_model.grant_perm(id, perm) - h.flash(_("Revoked 'repository create' permission to user"), - category='success') - Session().commit() + except Exception: + log.error(traceback.format_exc()) + h.flash(_('An error occurred during permissions saving'), + category='error') return redirect(url('edit_user', id=id)) def add_email(self, id): diff --git a/rhodecode/controllers/admin/users_groups.py b/rhodecode/controllers/admin/users_groups.py --- a/rhodecode/controllers/admin/users_groups.py +++ b/rhodecode/controllers/admin/users_groups.py @@ -34,13 +34,13 @@ from pylons.i18n.translation import _ from rhodecode.lib import helpers as h from rhodecode.lib.exceptions import UsersGroupsAssignedException -from rhodecode.lib.utils2 import safe_unicode +from rhodecode.lib.utils2 import safe_unicode, str2bool from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator from rhodecode.lib.base import BaseController, render from rhodecode.model.users_group import UsersGroupModel -from rhodecode.model.db import User, UsersGroup, Permission, UsersGroupToPerm +from rhodecode.model.db import User, UsersGroup from rhodecode.model.forms import UsersGroupForm from rhodecode.model.meta import Session from rhodecode.lib.utils import action_logger @@ -135,15 +135,20 @@ class UsersGroupsController(BaseControll h.flash(_('updated users group %s') % gr, category='success') Session().commit() except formencode.Invalid, errors: + ug_model = UsersGroupModel() + defaults = errors.value e = errors.error_dict or {} - - perm = Permission.get_by_key('hg.create.repository') - e.update({'create_repo_perm': - UsersGroupModel().has_perm(id, perm)}) + defaults.update({ + 'create_repo_perm': ug_model.has_perm(id, + 'hg.create.repository'), + 'fork_repo_perm': ug_model.has_perm(id, + 'hg.fork.repository'), + '_method': 'put' + }) return htmlfill.render( render('admin/users_groups/users_group_edit.html'), - defaults=errors.value, + defaults=defaults, errors=e, prefix_error=False, encoding="UTF-8") @@ -152,7 +157,7 @@ class UsersGroupsController(BaseControll h.flash(_('error occurred during update of users group %s') \ % request.POST.get('users_group_name'), category='error') - return redirect(url('users_groups')) + return redirect(url('edit_users_group', id=id)) def delete(self, id): """DELETE /users_groups/id: Delete an existing item""" @@ -162,9 +167,9 @@ class UsersGroupsController(BaseControll # h.form(url('users_group', id=ID), # method='delete') # url('users_group', id=ID) - + usr_gr = UsersGroup.get_or_404(id) try: - UsersGroupModel().delete(id) + UsersGroupModel().delete(usr_gr) Session().commit() h.flash(_('successfully deleted users group'), category='success') except UsersGroupsAssignedException, e: @@ -183,9 +188,7 @@ class UsersGroupsController(BaseControll """GET /users_groups/id/edit: Form to edit an existing item""" # url('edit_users_group', id=ID) - c.users_group = UsersGroup.get(id) - if not c.users_group: - return redirect(url('users_groups')) + c.users_group = UsersGroup.get_or_404(id) c.users_group.permissions = {} c.group_members_obj = [x.user for x in c.users_group.members] @@ -193,10 +196,15 @@ class UsersGroupsController(BaseControll c.group_members_obj] c.available_members = [(x.user_id, x.username) for x in User.query().all()] + ug_model = UsersGroupModel() defaults = c.users_group.get_dict() - perm = Permission.get_by_key('hg.create.repository') - defaults.update({'create_repo_perm': - UsersGroupModel().has_perm(c.users_group, perm)}) + defaults.update({ + 'create_repo_perm': ug_model.has_perm(c.users_group, + 'hg.create.repository'), + 'fork_repo_perm': ug_model.has_perm(c.users_group, + 'hg.fork.repository'), + }) + return htmlfill.render( render('admin/users_groups/users_group_edit.html'), defaults=defaults, @@ -208,25 +216,43 @@ class UsersGroupsController(BaseControll """PUT /users_perm/id: Update an existing item""" # url('users_group_perm', id=ID, method='put') - grant_perm = request.POST.get('create_repo_perm', False) + users_group = UsersGroup.get_or_404(id) + grant_create_perm = str2bool(request.POST.get('create_repo_perm')) + grant_fork_perm = str2bool(request.POST.get('fork_repo_perm')) + inherit_perms = str2bool(request.POST.get('inherit_default_permissions')) + + usersgroup_model = UsersGroupModel() + + try: + users_group.inherit_default_permissions = inherit_perms + Session().add(users_group) - if grant_perm: - perm = Permission.get_by_key('hg.create.none') - UsersGroupModel().revoke_perm(id, perm) + if grant_create_perm: + usersgroup_model.revoke_perm(id, 'hg.create.none') + usersgroup_model.grant_perm(id, 'hg.create.repository') + h.flash(_("Granted 'repository create' permission to users group"), + category='success') + else: + usersgroup_model.revoke_perm(id, 'hg.create.repository') + usersgroup_model.grant_perm(id, 'hg.create.none') + h.flash(_("Revoked 'repository create' permission to users group"), + category='success') - perm = Permission.get_by_key('hg.create.repository') - UsersGroupModel().grant_perm(id, perm) - h.flash(_("Granted 'repository create' permission to user"), - category='success') + if grant_fork_perm: + usersgroup_model.revoke_perm(id, 'hg.fork.none') + usersgroup_model.grant_perm(id, 'hg.fork.repository') + h.flash(_("Granted 'repository fork' permission to users group"), + category='success') + else: + usersgroup_model.revoke_perm(id, 'hg.fork.repository') + usersgroup_model.grant_perm(id, 'hg.fork.none') + h.flash(_("Revoked 'repository fork' permission to users group"), + category='success') Session().commit() - else: - perm = Permission.get_by_key('hg.create.repository') - UsersGroupModel().revoke_perm(id, perm) + except Exception: + log.error(traceback.format_exc()) + h.flash(_('An error occurred during permissions saving'), + category='error') - perm = Permission.get_by_key('hg.create.none') - UsersGroupModel().grant_perm(id, perm) - h.flash(_("Revoked 'repository create' permission to user"), - category='success') - Session().commit() return redirect(url('edit_users_group', id=id)) diff --git a/rhodecode/controllers/forks.py b/rhodecode/controllers/forks.py --- a/rhodecode/controllers/forks.py +++ b/rhodecode/controllers/forks.py @@ -35,7 +35,8 @@ import rhodecode.lib.helpers as h from rhodecode.lib.helpers import Page from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator, \ - NotAnonymous, HasRepoPermissionAny + NotAnonymous, HasRepoPermissionAny, HasPermissionAllDecorator,\ + HasPermissionAnyDecorator from rhodecode.lib.base import BaseRepoController, render from rhodecode.model.db import Repository, RepoGroup, UserFollowing, User from rhodecode.model.repo import RepoModel @@ -123,6 +124,7 @@ class ForksController(BaseRepoController return render('/forks/forks.html') @NotAnonymous() + @HasPermissionAnyDecorator('hg.admin', 'hg.fork.repository') @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', 'repository.admin') def fork(self, repo_name): @@ -146,6 +148,7 @@ class ForksController(BaseRepoController ) @NotAnonymous() + @HasPermissionAnyDecorator('hg.admin', 'hg.fork.repository') @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', 'repository.admin') def fork_create(self, repo_name): diff --git a/rhodecode/lib/auth.py b/rhodecode/lib/auth.py --- a/rhodecode/lib/auth.py +++ b/rhodecode/lib/auth.py @@ -350,6 +350,7 @@ class AuthUser(object): log.debug('Auth User lookup by USER NAME %s' % self.username) dbuser = login_container_auth(self.username) if dbuser is not None: + log.debug('filling all attributes to object') for k, v in dbuser.get_dict().items(): setattr(self, k, v) self.set_authenticated() diff --git a/rhodecode/lib/db_manage.py b/rhodecode/lib/db_manage.py --- a/rhodecode/lib/db_manage.py +++ b/rhodecode/lib/db_manage.py @@ -513,27 +513,32 @@ class DbManage(object): def populate_default_permissions(self): log.info('creating default user permissions') - default_user = self.sa.query(User)\ - .filter(User.username == 'default').scalar() + default_user = User.get_by_username('default') reg_perm = UserToPerm() reg_perm.user = default_user reg_perm.permission = self.sa.query(Permission)\ - .filter(Permission.permission_name == 'hg.register.manual_activate')\ - .scalar() + .filter(Permission.permission_name == 'hg.register.manual_activate')\ + .scalar() + self.sa.add(reg_perm) create_repo_perm = UserToPerm() create_repo_perm.user = default_user create_repo_perm.permission = self.sa.query(Permission)\ - .filter(Permission.permission_name == 'hg.create.repository')\ - .scalar() + .filter(Permission.permission_name == 'hg.create.repository')\ + .scalar() + self.sa.add(create_repo_perm) + + default_fork_perm = UserToPerm() + default_fork_perm.user = default_user + default_fork_perm.permission = self.sa.query(Permission)\ + .filter(Permission.permission_name == 'hg.fork.repository')\ + .scalar() + self.sa.add(default_fork_perm) default_repo_perm = UserToPerm() default_repo_perm.user = default_user default_repo_perm.permission = self.sa.query(Permission)\ - .filter(Permission.permission_name == 'repository.read')\ - .scalar() - - self.sa.add(reg_perm) - self.sa.add(create_repo_perm) + .filter(Permission.permission_name == 'repository.read')\ + .scalar() self.sa.add(default_repo_perm) diff --git a/rhodecode/model/db.py b/rhodecode/model/db.py --- a/rhodecode/model/db.py +++ b/rhodecode/model/db.py @@ -294,6 +294,7 @@ class User(Base, BaseModel): last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None) ldap_dn = Column("ldap_dn", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) api_key = Column("api_key", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) + inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True) user_log = relationship('UserLog', cascade='all') user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all') @@ -504,6 +505,7 @@ class UsersGroup(Base, BaseModel): users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) users_group_name = Column("users_group_name", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None) users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None) + inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True) members = relationship('UsersGroupMember', cascade="all, delete, delete-orphan", lazy="joined") users_group_to_perm = relationship('UsersGroupToPerm', cascade='all') @@ -1084,6 +1086,8 @@ class Permission(Base, BaseModel): ('hg.admin', _('RhodeCode Administrator')), ('hg.create.none', _('Repository creation disabled')), ('hg.create.repository', _('Repository creation enabled')), + ('hg.fork.none', _('Repository forking disabled')), + ('hg.fork.repository', _('Repository forking enabled')), ('hg.register.none', _('Register disabled')), ('hg.register.manual_activate', _('Register new user with RhodeCode ' 'with manual activation')), @@ -1092,6 +1096,24 @@ class Permission(Base, BaseModel): 'with auto activation')), ] + # defines which permissions are more important higher the more important + PERM_WEIGHTS = { + 'repository.none': 0, + 'repository.read': 1, + 'repository.write': 3, + 'repository.admin': 4, + + 'group.none': 0, + 'group.read': 1, + 'group.write': 3, + 'group.admin': 4, + + 'hg.fork.none': 0, + 'hg.fork.repository': 1, + 'hg.create.none': 0, + 'hg.create.repository':1 + } + permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) permission_name = Column("permission_name", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) permission_longname = Column("permission_longname", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) diff --git a/rhodecode/model/forms.py b/rhodecode/model/forms.py --- a/rhodecode/model/forms.py +++ b/rhodecode/model/forms.py @@ -274,7 +274,8 @@ def ApplicationUiSettingsForm(): return _ApplicationUiSettingsForm -def DefaultPermissionsForm(perms_choices, register_choices, create_choices): +def DefaultPermissionsForm(perms_choices, register_choices, create_choices, + fork_choices): class _DefaultPermissionsForm(formencode.Schema): allow_extra_fields = True filter_extra_fields = True @@ -283,6 +284,7 @@ def DefaultPermissionsForm(perms_choices default_perm = v.OneOf(perms_choices) default_register = v.OneOf(register_choices) default_create = v.OneOf(create_choices) + default_fork = v.OneOf(fork_choices) return _DefaultPermissionsForm diff --git a/rhodecode/model/permission.py b/rhodecode/model/permission.py --- a/rhodecode/model/permission.py +++ b/rhodecode/model/permission.py @@ -77,8 +77,8 @@ class PermissionModel(BaseModel): form_result['perm_user_name']).scalar() u2p = self.sa.query(UserToPerm).filter(UserToPerm.user == perm_user).all() - if len(u2p) != 3: - raise Exception('Defined: %s should be 3 permissions for default' + if len(u2p) != 4: + raise Exception('Defined: %s should be 4 permissions for default' ' user. This should not happen please verify' ' your database' % len(u2p)) @@ -100,6 +100,11 @@ class PermissionModel(BaseModel): form_result['default_create']) self.sa.add(p) + elif p.permission.permission_name.startswith('hg.fork.'): + p.permission = self.get_permission_by_name( + form_result['default_fork']) + self.sa.add(p) + _def_name = form_result['default_perm'].split('repository.')[-1] #stage 2 update all default permissions for repos if checked if form_result['overwrite_default'] == True: diff --git a/rhodecode/model/user.py b/rhodecode/model/user.py --- a/rhodecode/model/user.py +++ b/rhodecode/model/user.py @@ -25,7 +25,7 @@ import logging import traceback - +import itertools from pylons import url from pylons.i18n.translation import _ @@ -45,17 +45,7 @@ from rhodecode.lib.exceptions import Def log = logging.getLogger(__name__) - -PERM_WEIGHTS = { - 'repository.none': 0, - 'repository.read': 1, - 'repository.write': 3, - 'repository.admin': 4, - 'group.none': 0, - 'group.read': 1, - 'group.write': 3, - 'group.admin': 4, -} +PERM_WEIGHTS = Permission.PERM_WEIGHTS class UserModel(BaseModel): @@ -432,11 +422,11 @@ class UserModel(BaseModel): return user #================================================================== - # set default permissions first for repositories and groups + # SET DEFAULTS GLOBAL, REPOS, REPOS GROUPS #================================================================== uid = user.user_id - # default global permissions + # default global permissions taken fron the default user default_global_perms = self.sa.query(UserToPerm)\ .filter(UserToPerm.user_id == default_user_id) @@ -464,25 +454,89 @@ class UserModel(BaseModel): p = perm.Permission.permission_name user.permissions[GK][rg_k] = p - #================================================================== - # overwrite defaults with user permissions if any found - #================================================================== + #====================================================================== + # !! OVERRIDE GLOBALS !! with user permissions if any found + #====================================================================== + # those can be configured from groups or users explicitly + _configurable = set(['hg.fork.none', 'hg.fork.repository', + 'hg.create.none', 'hg.create.repository']) - # user global permissions + # USER GROUPS comes first + # users group global permissions + user_perms_from_users_groups = self.sa.query(UsersGroupToPerm)\ + .options(joinedload(UsersGroupToPerm.permission))\ + .join((UsersGroupMember, UsersGroupToPerm.users_group_id == + UsersGroupMember.users_group_id))\ + .filter(UsersGroupMember.user_id == uid)\ + .order_by(UsersGroupToPerm.users_group_id)\ + .all() + #need to group here by groups since user can be in more than one group + _grouped = [[x, list(y)] for x, y in + itertools.groupby(user_perms_from_users_groups, + lambda x:x.users_group)] + for gr, perms in _grouped: + # since user can be in multiple groups iterate over them and + # select the lowest permissions first (more explicit) + ##TODO: do this^^ + if not gr.inherit_default_permissions: + # NEED TO IGNORE all configurable permissions and + # replace them with explicitly set + user.permissions[GLOBAL] = user.permissions[GLOBAL]\ + .difference(_configurable) + for perm in perms: + user.permissions[GLOBAL].add(perm.permission.permission_name) + + # user specific global permissions user_perms = self.sa.query(UserToPerm)\ .options(joinedload(UserToPerm.permission))\ .filter(UserToPerm.user_id == uid).all() - for perm in user_perms: - user.permissions[GLOBAL].add(perm.permission.permission_name) + if not user.inherit_default_permissions: + # NEED TO IGNORE all configurable permissions and + # replace them with explicitly set + user.permissions[GLOBAL] = user.permissions[GLOBAL]\ + .difference(_configurable) + + for perm in user_perms: + user.permissions[GLOBAL].add(perm.permission.permission_name) + + #====================================================================== + # !! REPO PERMISSIONS !! + #====================================================================== + #====================================================================== + # check if user is part of user groups for this repository and + # fill in (or NOT replace with higher `or 1` permissions + #====================================================================== + # users group for repositories permissions + user_repo_perms_from_users_groups = \ + self.sa.query(UsersGroupRepoToPerm, Permission, Repository,)\ + .join((Repository, UsersGroupRepoToPerm.repository_id == + Repository.repo_id))\ + .join((Permission, UsersGroupRepoToPerm.permission_id == + Permission.permission_id))\ + .join((UsersGroupMember, UsersGroupRepoToPerm.users_group_id == + UsersGroupMember.users_group_id))\ + .filter(UsersGroupMember.user_id == uid)\ + .all() + + for perm in user_repo_perms_from_users_groups: + r_k = perm.UsersGroupRepoToPerm.repository.repo_name + p = perm.Permission.permission_name + cur_perm = user.permissions[RK][r_k] + # overwrite permission only if it's greater than permission + # given from other sources + if PERM_WEIGHTS[p] > PERM_WEIGHTS[cur_perm] or 1: # disable check + user.permissions[RK][r_k] = p # user explicit permissions for repositories user_repo_perms = \ self.sa.query(UserRepoToPerm, Permission, Repository)\ - .join((Repository, UserRepoToPerm.repository_id == Repository.repo_id))\ - .join((Permission, UserRepoToPerm.permission_id == Permission.permission_id))\ - .filter(UserRepoToPerm.user_id == uid)\ - .all() + .join((Repository, UserRepoToPerm.repository_id == + Repository.repo_id))\ + .join((Permission, UserRepoToPerm.permission_id == + Permission.permission_id))\ + .filter(UserRepoToPerm.user_id == uid)\ + .all() for perm in user_repo_perms: # set admin if owner @@ -493,40 +547,6 @@ class UserModel(BaseModel): p = perm.Permission.permission_name user.permissions[RK][r_k] = p - # USER GROUP - #================================================================== - # check if user is part of user groups for this repository and - # fill in (or replace with higher) permissions - #================================================================== - - # users group global - user_perms_from_users_groups = self.sa.query(UsersGroupToPerm)\ - .options(joinedload(UsersGroupToPerm.permission))\ - .join((UsersGroupMember, UsersGroupToPerm.users_group_id == - UsersGroupMember.users_group_id))\ - .filter(UsersGroupMember.user_id == uid).all() - - for perm in user_perms_from_users_groups: - user.permissions[GLOBAL].add(perm.permission.permission_name) - - # users group for repositories permissions - user_repo_perms_from_users_groups = \ - self.sa.query(UsersGroupRepoToPerm, Permission, Repository,)\ - .join((Repository, UsersGroupRepoToPerm.repository_id == Repository.repo_id))\ - .join((Permission, UsersGroupRepoToPerm.permission_id == Permission.permission_id))\ - .join((UsersGroupMember, UsersGroupRepoToPerm.users_group_id == UsersGroupMember.users_group_id))\ - .filter(UsersGroupMember.user_id == uid)\ - .all() - - for perm in user_repo_perms_from_users_groups: - r_k = perm.UsersGroupRepoToPerm.repository.repo_name - p = perm.Permission.permission_name - cur_perm = user.permissions[RK][r_k] - # overwrite permission only if it's greater than permission - # given from other sources - if PERM_WEIGHTS[p] > PERM_WEIGHTS[cur_perm]: - user.permissions[RK][r_k] = p - # REPO GROUP #================================================================== # get access for this user for repos group and override defaults @@ -574,10 +594,7 @@ class UserModel(BaseModel): return user def has_perm(self, user, perm): - if not isinstance(perm, Permission): - raise Exception('perm needs to be an instance of Permission class ' - 'got %s instead' % type(perm)) - + perm = self._get_perm(perm) user = self._get_user(user) return UserToPerm.query().filter(UserToPerm.user == user)\ diff --git a/rhodecode/model/users_group.py b/rhodecode/model/users_group.py --- a/rhodecode/model/users_group.py +++ b/rhodecode/model/users_group.py @@ -165,10 +165,8 @@ class UsersGroupModel(BaseModel): .filter(UsersGroupToPerm.permission == perm).scalar() is not None def grant_perm(self, users_group, perm): - if not isinstance(perm, Permission): - raise Exception('perm needs to be an instance of Permission class') - users_group = self.__get_users_group(users_group) + perm = self._get_perm(perm) # if this permission is already granted skip it _perm = UsersGroupToPerm.query()\ diff --git a/rhodecode/templates/admin/permissions/permissions.html b/rhodecode/templates/admin/permissions/permissions.html --- a/rhodecode/templates/admin/permissions/permissions.html +++ b/rhodecode/templates/admin/permissions/permissions.html @@ -37,7 +37,7 @@