diff --git a/rhodecode/controllers/admin/repos_groups.py b/rhodecode/controllers/admin/repos_groups.py --- a/rhodecode/controllers/admin/repos_groups.py +++ b/rhodecode/controllers/admin/repos_groups.py @@ -45,6 +45,7 @@ from rhodecode.model.forms import ReposG from rhodecode.model.meta import Session from rhodecode.model.repo import RepoModel from webob.exc import HTTPInternalServerError, HTTPNotFound +from rhodecode.lib.utils2 import str2bool log = logging.getLogger(__name__) @@ -162,7 +163,7 @@ class ReposGroupsController(BaseControll Session().commit() h.flash(_('updated repos group %s') \ % form_result['group_name'], category='success') - #TODO: in futureaction_logger(, '', '', '', self.sa) + #TODO: in future action_logger(, '', '', '', self.sa) except formencode.Invalid, errors: return htmlfill.render( @@ -227,10 +228,11 @@ class ReposGroupsController(BaseControll :param group_name: """ - try: - ReposGroupModel().revoke_user_permission( - repos_group=group_name, user=request.POST['user_id'] + recursive = str2bool(request.POST.get('recursive', False)) + ReposGroupModel().delete_permission( + repos_group=group_name, obj=request.POST['user_id'], + obj_type='user', recursive=recursive ) Session().commit() except Exception: @@ -248,9 +250,10 @@ class ReposGroupsController(BaseControll """ try: - ReposGroupModel().revoke_users_group_permission( - repos_group=group_name, - group_name=request.POST['users_group_id'] + recursive = str2bool(request.POST.get('recursive', False)) + ReposGroupModel().delete_permission( + repos_group=group_name, obj=request.POST['users_group_id'], + obj_type='users_group', recursive=recursive ) Session().commit() except Exception: diff --git a/rhodecode/model/forms.py b/rhodecode/model/forms.py --- a/rhodecode/model/forms.py +++ b/rhodecode/model/forms.py @@ -128,6 +128,7 @@ def ReposGroupForm(edit=False, old_data= testValueList=True, if_missing=None, not_empty=False) enable_locking = v.StringBoolean(if_missing=False) + recursive = v.StringBoolean(if_missing=False) chained_validators = [v.ValidReposGroup(edit, old_data), v.ValidPerms('group')] diff --git a/rhodecode/model/repo.py b/rhodecode/model/repo.py --- a/rhodecode/model/repo.py +++ b/rhodecode/model/repo.py @@ -368,6 +368,7 @@ class RepoModel(BaseModel): obj.user = user obj.permission = permission self.sa.add(obj) + log.debug('Granted perm %s to %s on %s' % (perm, user, repo)) def revoke_user_permission(self, repo, user): """ @@ -383,8 +384,10 @@ class RepoModel(BaseModel): obj = self.sa.query(UserRepoToPerm)\ .filter(UserRepoToPerm.repository == repo)\ .filter(UserRepoToPerm.user == user)\ - .one() - self.sa.delete(obj) + .scalar() + if obj: + self.sa.delete(obj) + log.debug('Revoked perm on %s on %s' % (repo, user)) def grant_users_group_permission(self, repo, group_name, perm): """ @@ -414,6 +417,7 @@ class RepoModel(BaseModel): obj.users_group = group_name obj.permission = permission self.sa.add(obj) + log.debug('Granted perm %s to %s on %s' % (perm, group_name, repo)) def revoke_users_group_permission(self, repo, group_name): """ @@ -429,8 +433,10 @@ class RepoModel(BaseModel): obj = self.sa.query(UsersGroupRepoToPerm)\ .filter(UsersGroupRepoToPerm.repository == repo)\ .filter(UsersGroupRepoToPerm.users_group == group_name)\ - .one() - self.sa.delete(obj) + .scalar() + if obj: + self.sa.delete(obj) + log.debug('Revoked perm to %s on %s' % (repo, group_name)) def delete_stats(self, repo_name): """ diff --git a/rhodecode/model/repos_group.py b/rhodecode/model/repos_group.py --- a/rhodecode/model/repos_group.py +++ b/rhodecode/model/repos_group.py @@ -32,7 +32,7 @@ from rhodecode.lib.utils2 import LazyPro from rhodecode.model import BaseModel from rhodecode.model.db import RepoGroup, RhodeCodeUi, UserRepoGroupToPerm, \ - User, Permission, UsersGroupRepoGroupToPerm, UsersGroup + User, Permission, UsersGroupRepoGroupToPerm, UsersGroup, Repository log = logging.getLogger(__name__) @@ -115,11 +115,12 @@ class ReposGroupModel(BaseModel): 'existing dir %s' % new_path) shutil.move(old_path, new_path) - def __delete_group(self, group): + def __delete_group(self, group, force_delete=False): """ Deletes a group from a filesystem :param group: instance of group from database + :param force_delete: use shutil rmtree to remove all objects """ paths = group.full_path.split(RepoGroup.url_sep()) paths = os.sep.join(paths) @@ -127,7 +128,10 @@ class ReposGroupModel(BaseModel): rm_path = os.path.join(self.repos_path, paths) if os.path.isdir(rm_path): # delete only if that path really exists - os.rmdir(rm_path) + if force_delete: + shutil.rmtree(rm_path) + else: + os.rmdir(rm_path) # this raises an exception when there are still objects inside def create(self, group_name, group_description, parent=None, just_db=False): try: @@ -150,32 +154,79 @@ class ReposGroupModel(BaseModel): log.error(traceback.format_exc()) raise + def _update_permissions(self, repos_group, perms_new=None, + perms_updates=None, recursive=False): + from rhodecode.model.repo import RepoModel + if not perms_new: + perms_new = [] + if not perms_updates: + perms_updates = [] + + def _set_perm_user(obj, user, perm): + if isinstance(obj, RepoGroup): + ReposGroupModel().grant_user_permission( + repos_group=obj, user=user, perm=perm + ) + elif isinstance(obj, Repository): + # we set group permission but we have to switch to repo + # permission + perm = perm.replace('group.', 'repository.') + RepoModel().grant_user_permission( + repo=obj, user=user, perm=perm + ) + + def _set_perm_group(obj, users_group, perm): + if isinstance(obj, RepoGroup): + ReposGroupModel().grant_users_group_permission( + repos_group=obj, group_name=users_group, perm=perm + ) + elif isinstance(obj, Repository): + # we set group permission but we have to switch to repo + # permission + perm = perm.replace('group.', 'repository.') + RepoModel().grant_users_group_permission( + repo=obj, group_name=users_group, perm=perm + ) + updates = [] + log.debug('Now updating permissions for %s in recursive mode:%s' + % (repos_group, recursive)) + + for obj in repos_group.recursive_groups_and_repos(): + if not recursive: + obj = repos_group + + # update permissions + for member, perm, member_type in perms_updates: + ## set for user + if member_type == 'user': + # this updates also current one if found + _set_perm_user(obj, user=member, perm=perm) + ## set for users group + else: + _set_perm_group(obj, users_group=member, perm=perm) + # set new permissions + for member, perm, member_type in perms_new: + if member_type == 'user': + _set_perm_user(obj, user=member, perm=perm) + else: + _set_perm_group(obj, users_group=member, perm=perm) + updates.append(obj) + #if it's not recursive call + # break the loop and don't proceed with other changes + if not recursive: + break + return updates + def update(self, repos_group_id, form_data): try: repos_group = RepoGroup.get(repos_group_id) - - # update permissions - for member, perm, member_type in form_data['perms_updates']: - if member_type == 'user': - # this updates also current one if found - ReposGroupModel().grant_user_permission( - repos_group=repos_group, user=member, perm=perm - ) - else: - ReposGroupModel().grant_users_group_permission( - repos_group=repos_group, group_name=member, perm=perm - ) - # set new permissions - for member, perm, member_type in form_data['perms_new']: - if member_type == 'user': - ReposGroupModel().grant_user_permission( - repos_group=repos_group, user=member, perm=perm - ) - else: - ReposGroupModel().grant_users_group_permission( - repos_group=repos_group, group_name=member, perm=perm - ) + recursive = form_data['recursive'] + # iterate over all members(if in recursive mode) of this groups and + # set the permissions ! + # this can be potentially heavy operation + self._update_permissions(repos_group, form_data['perms_new'], + form_data['perms_updates'], recursive) old_path = repos_group.full_path @@ -191,7 +242,6 @@ class ReposGroupModel(BaseModel): # iterate over all members of this groups and set the locking ! # this can be potentially heavy operation - for obj in repos_group.recursive_groups_and_repos(): #set the value from it's parent obj.enable_locking = repos_group.enable_locking @@ -210,15 +260,54 @@ class ReposGroupModel(BaseModel): log.error(traceback.format_exc()) raise - def delete(self, repos_group): + def delete(self, repos_group, force_delete=False): repos_group = self._get_repos_group(repos_group) try: self.sa.delete(repos_group) - self.__delete_group(repos_group) + self.__delete_group(repos_group, force_delete) except: log.exception('Error removing repos_group %s' % repos_group) raise + def delete_permission(self, repos_group, obj, obj_type, recursive): + """ + Revokes permission for repos_group for given obj(user or users_group), + obj_type can be user or users group + + :param repos_group: + :param obj: user or users group id + :param obj_type: user or users group type + :param recursive: recurse to all children of group + """ + from rhodecode.model.repo import RepoModel + repos_group = self._get_repos_group(repos_group) + + for el in repos_group.recursive_groups_and_repos(): + if not recursive: + # if we don't recurse set the permission on only the top level + # object + el = repos_group + + if isinstance(el, RepoGroup): + if obj_type == 'user': + ReposGroupModel().revoke_user_permission(el, user=obj) + elif obj_type == 'users_group': + ReposGroupModel().revoke_users_group_permission(el, group_name=obj) + else: + raise Exception('undefined object type %s' % obj_type) + elif isinstance(el, Repository): + if obj_type == 'user': + RepoModel().revoke_user_permission(el, user=obj) + elif obj_type == 'users_group': + RepoModel().revoke_users_group_permission(el, group_name=obj) + else: + raise Exception('undefined object type %s' % obj_type) + + #if it's not recursive call + # break the loop and don't proceed with other changes + if not recursive: + break + def grant_user_permission(self, repos_group, user, perm): """ Grant permission for user on given repositories group, or update @@ -246,6 +335,7 @@ class ReposGroupModel(BaseModel): obj.user = user obj.permission = permission self.sa.add(obj) + log.debug('Granted perm %s to %s on %s' % (perm, user, repos_group)) def revoke_user_permission(self, repos_group, user): """ @@ -262,8 +352,10 @@ class ReposGroupModel(BaseModel): obj = self.sa.query(UserRepoGroupToPerm)\ .filter(UserRepoGroupToPerm.user == user)\ .filter(UserRepoGroupToPerm.group == repos_group)\ - .one() - self.sa.delete(obj) + .scalar() + if obj: + self.sa.delete(obj) + log.debug('Revoked perm on %s on %s' % (repos_group, user)) def grant_users_group_permission(self, repos_group, group_name, perm): """ @@ -294,6 +386,7 @@ class ReposGroupModel(BaseModel): obj.users_group = group_name obj.permission = permission self.sa.add(obj) + log.debug('Granted perm %s to %s on %s' % (perm, group_name, repos_group)) def revoke_users_group_permission(self, repos_group, group_name): """ @@ -310,5 +403,7 @@ class ReposGroupModel(BaseModel): obj = self.sa.query(UsersGroupRepoGroupToPerm)\ .filter(UsersGroupRepoGroupToPerm.group == repos_group)\ .filter(UsersGroupRepoGroupToPerm.users_group == group_name)\ - .one() - self.sa.delete(obj) + .scalar() + if obj: + self.sa.delete(obj) + log.debug('Revoked perm to %s on %s' % (repos_group, group_name)) diff --git a/rhodecode/model/user.py b/rhodecode/model/user.py --- a/rhodecode/model/user.py +++ b/rhodecode/model/user.py @@ -564,7 +564,7 @@ class UserModel(BaseModel): rg_k = perm.UserRepoGroupToPerm.group.group_name p = perm.Permission.permission_name cur_perm = user.permissions[GK][rg_k] - if PERM_WEIGHTS[p] > PERM_WEIGHTS[cur_perm]: + if PERM_WEIGHTS[p] > PERM_WEIGHTS[cur_perm] or 1: # disable check user.permissions[GK][rg_k] = p # REPO GROUP + USER GROUP @@ -588,7 +588,7 @@ class UserModel(BaseModel): cur_perm = user.permissions[GK][g_k] # overwrite permission only if it's greater than permission # given from other sources - if PERM_WEIGHTS[p] > PERM_WEIGHTS[cur_perm]: + if PERM_WEIGHTS[p] > PERM_WEIGHTS[cur_perm] or 1: # disable check user.permissions[GK][g_k] = p return user diff --git a/rhodecode/model/validators.py b/rhodecode/model/validators.py --- a/rhodecode/model/validators.py +++ b/rhodecode/model/validators.py @@ -499,9 +499,9 @@ def ValidPerms(type_='repo'): # fill new permissions in order of how they were added for k in sorted(map(int, new_perms_group.keys())): perm_dict = new_perms_group[str(k)] - new_member = perm_dict['name'] - new_perm = perm_dict['perm'] - new_type = perm_dict['type'] + new_member = perm_dict.get('name') + new_perm = perm_dict.get('perm') + new_type = perm_dict.get('type') if new_member and new_perm and new_type: perms_new.add((new_member, new_perm, new_type)) diff --git a/rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html b/rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html --- a/rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html +++ b/rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html @@ -68,6 +68,12 @@ + + + ${h.checkbox('recursive',value="True", label=_('apply to parents'))} + ${_('Set or revoke permission to all children of that group, including repositories and other groups')} + +