def update_perms(self, group_name): """ Update permissions for given repository group :param group_name: """ c.repo_group = RepoGroupModel()._get_repo_group(group_name) valid_recursive_choices = ['none', 'repos', 'groups', 'all'] form = RepoGroupPermsForm(valid_recursive_choices)().to_python( request.POST) if not c.rhodecode_user.is_admin: if self._revoke_perms_on_yourself(form): msg = _('Cannot change permission for yourself as admin') h.flash(msg, category='warning') return redirect( url('edit_repo_group_perms', group_name=group_name)) # iterate over all members(if in recursive mode) of this groups and # set the permissions ! # this can be potentially heavy operation RepoGroupModel().update_permissions(c.repo_group, form['perm_additions'], form['perm_updates'], form['perm_deletions'], form['recursive']) # TODO: implement this # action_logger(c.rhodecode_user, 'admin_changed_repo_permissions', # repo_name, self.ip_addr, self.sa) Session().commit() h.flash(_('Repository Group permissions updated'), category='success') return redirect(url('edit_repo_group_perms', group_name=group_name))
def test_repo_in_group_permissions(self): self.g1 = fixture.create_repo_group('group1', skip_if_exists=True) self.g2 = fixture.create_repo_group('group2', skip_if_exists=True) # both perms should be read ! assert group_perms(self.u1) == \ {u'group1': u'group.read', u'group2': u'group.read'} assert group_perms(self.anon) == \ {u'group1': u'group.read', u'group2': u'group.read'} # Change perms to none for both groups RepoGroupModel().grant_user_permission(repo_group=self.g1, user=self.anon, perm='group.none') RepoGroupModel().grant_user_permission(repo_group=self.g2, user=self.anon, perm='group.none') assert group_perms(self.u1) == \ {u'group1': u'group.none', u'group2': u'group.none'} assert group_perms(self.anon) == \ {u'group1': u'group.none', u'group2': u'group.none'} # add repo to group name = RepoGroup.url_sep().join([self.g1.group_name, 'test_perm']) self.test_repo = fixture.create_repo( name=name, repo_type='hg', repo_group=self.g1, cur_user=self.u1, ) assert group_perms(self.u1) == \ {u'group1': u'group.none', u'group2': u'group.none'} assert group_perms(self.anon) == \ {u'group1': u'group.none', u'group2': u'group.none'} # grant permission for u2 ! RepoGroupModel().grant_user_permission(repo_group=self.g1, user=self.u2, perm='group.read') RepoGroupModel().grant_user_permission(repo_group=self.g2, user=self.u2, perm='group.read') Session().commit() assert self.u1 != self.u2 # u1 and anon should have not change perms while u2 should ! assert group_perms(self.u1) == \ {u'group1': u'group.none', u'group2': u'group.none'} assert group_perms(self.u2) == \ {u'group1': u'group.read', u'group2': u'group.read'} assert group_perms(self.anon) == \ {u'group1': u'group.none', u'group2': u'group.none'}
def update_repo_group( request, apiuser, repogroupid, group_name=Optional(''), description=Optional(''), owner=Optional(OAttr('apiuser')), parent=Optional(None), enable_locking=Optional(False)): """ Updates repository group with the details given. This command can only be run using an |authtoken| with admin permissions. :param apiuser: This is filled automatically from the |authtoken|. :type apiuser: AuthUser :param repogroupid: Set the ID of repository group. :type repogroupid: str or int :param group_name: Set the name of the |repo| group. :type group_name: str :param description: Set a description for the group. :type description: str :param owner: Set the |repo| group owner. :type owner: str :param parent: Set the |repo| group parent. :type parent: str or int :param enable_locking: Enable |repo| locking. The default is false. :type enable_locking: bool """ repo_group = get_repo_group_or_error(repogroupid) if not has_superadmin_permission(apiuser): # check if we have admin permission for this repo group ! _perms = ('group.admin',) if not HasRepoGroupPermissionAnyApi(*_perms)( user=apiuser, group_name=repo_group.group_name): raise JSONRPCError( 'repository group `%s` does not exist' % (repogroupid,)) updates = {} try: store_update(updates, group_name, 'group_name') store_update(updates, description, 'group_description') store_update(updates, owner, 'user') store_update(updates, parent, 'group_parent_id') store_update(updates, enable_locking, 'enable_locking') repo_group = RepoGroupModel().update(repo_group, updates) Session().commit() return { 'msg': 'updated repository group ID:%s %s' % ( repo_group.group_id, repo_group.group_name), 'repo_group': repo_group.get_api_data() } except Exception: log.exception("Exception occurred while trying update repo group") raise JSONRPCError('failed to update repository group `%s`' % (repogroupid,))
def repo_group(request): model = RepoGroupModel() gr = model.create( group_name='test_gr', group_description='desc', just_db=True, owner=TEST_USER_ADMIN_LOGIN) def cleanup(): model.delete(gr) request.addfinalizer(cleanup) return gr
def test_update_parent(self, user_util): parent_group = user_util.create_repo_group() initial_name = self._update(user_util, parent=parent_group.name) expected_group_name = '{}/{}'.format(parent_group.name, initial_name) repo_group = RepoGroupModel()._get_repo_group(expected_group_name) assert repo_group is not None assert repo_group.group_name == expected_group_name assert repo_group.name == initial_name assert RepoGroupModel()._get_repo_group(initial_name) is None new_path = os.path.join( RepoGroupModel().repos_path, *repo_group.full_path_splitted) assert os.path.exists(new_path)
def update(self, group_name): """PUT /repo_groups/group_name: Update an existing item""" # Forms posted to this method should contain a hidden field: # <input type="hidden" name="_method" value="PUT" /> # Or using helpers: # h.form(url('repos_group', group_name=GROUP_NAME), method='put') # url('repo_group_home', group_name=GROUP_NAME) c.repo_group = RepoGroupModel()._get_repo_group(group_name) can_create_in_root = self._can_create_repo_group() show_root_location = can_create_in_root if not c.repo_group.parent_group: # this group don't have a parrent so we should show empty value show_root_location = True self.__load_defaults(allow_empty_group=show_root_location, repo_group=c.repo_group) repo_group_form = RepoGroupForm(edit=True, old_data=c.repo_group.get_dict(), available_groups=c.repo_groups_choices, can_create_in_root=can_create_in_root, allow_disabled=True)() try: form_result = repo_group_form.to_python(dict(request.POST)) gr_name = form_result['group_name'] new_gr = RepoGroupModel().update(group_name, form_result) Session().commit() h.flash(_('Updated repository group %s') % (gr_name, ), category='success') # we now have new name ! group_name = new_gr.group_name # TODO: in future action_logger(, '', '', '', self.sa) except formencode.Invalid as errors: c.active = 'settings' return htmlfill.render( render('admin/repo_groups/repo_group_edit.html'), defaults=errors.value, errors=errors.error_dict or {}, prefix_error=False, encoding="UTF-8", force_defaults=False) except Exception: log.exception("Exception during update or repository group") h.flash(_('Error occurred during update of repository group %s') % request.POST.get('group_name'), category='error') return redirect(url('edit_repo_group', group_name=group_name))
def test_api_delete_repo_group_regular_user(self, user_util): repo_group = user_util.create_repo_group(auto_cleanup=False) repo_group_name = repo_group.group_name repo_group_id = repo_group.group_id user = UserModel().get_by_username(self.TEST_USER_LOGIN) user_util.grant_user_permission_to_repo_group(repo_group, user, 'group.admin') id_, params = build_data( self.apikey, 'delete_repo_group', repogroupid=repo_group_name, ) response = api_call(self.app, params) ret = { 'msg': 'deleted repo group ID:%s %s' % (repo_group_id, repo_group_name), 'repo_group': None } expected = ret assert_ok(id_, expected, given=response.body) gr = RepoGroupModel()._get_repo_group(repo_group_name) assert gr is None
def test_create_subgroup(self, user_util): self.log_user() repo_group_name = self.NEW_REPO_GROUP parent_group = user_util.create_repo_group() parent_group_name = parent_group.group_name expected_group_name = '{}/{}'.format(parent_group_name, repo_group_name) expected_group_name_unicode = expected_group_name.decode('utf8') try: response = self.app.post( url('repo_groups'), fixture._get_group_create_params( group_name=repo_group_name, group_parent_id=parent_group.group_id, group_description='Test desciption', csrf_token=self.csrf_token)) assert_session_flash( response, u'Created repository group <a href="%s">%s</a>' % (h.url('repo_group_home', group_name=expected_group_name), expected_group_name_unicode)) finally: RepoGroupModel().delete(expected_group_name_unicode) Session().commit()
def permissions_setup_func(group_name='g0', perm='group.read', recursive='all', user_id=None): """ Resets all permissions to perm attribute """ if not user_id: user_id = test_u1_id # called by the @with_setup decorator also reset the default user stuff permissions_setup_func(group_name, perm, recursive, user_id=User.get_default_user().user_id) # TODO: DRY, compare test_user_group:permissions_setup_func repo_group = RepoGroup.get_by_group_name(group_name=group_name) if not repo_group: raise Exception('Cannot get group %s' % group_name) perm_updates = [[user_id, perm, 'user']] RepoGroupModel().update_permissions(repo_group, perm_updates=perm_updates, recursive=recursive, check_perms=False) Session().commit()
def edit_repo_group_advanced(self, group_name): """GET /repo_groups/group_name/edit: Form to edit an existing item""" # url('edit_repo_group', group_name=GROUP_NAME) c.active = 'advanced' c.repo_group = RepoGroupModel()._get_repo_group(group_name) return render('admin/repo_groups/repo_group_edit.html')
def test_api_grant_user_group_permission_to_repo_group( self, name, perm, apply_to_children, user_util): user_group = user_util.create_user_group() repo_group = user_util.create_repo_group() id_, params = build_data( self.apikey, 'grant_user_group_permission_to_repo_group', repogroupid=repo_group.name, usergroupid=user_group.users_group_name, perm=perm, apply_to_children=apply_to_children, ) response = api_call(self.app, params) ret = { 'msg': ('Granted perm: `%s` (recursive:%s) for user group: `%s`' ' in repo group: `%s`' % (perm, apply_to_children, user_group.users_group_name, repo_group.name)), 'success': True } expected = ret try: assert_ok(id_, expected, given=response.body) finally: RepoGroupModel().revoke_user_group_permission( repo_group.group_id, user_group.users_group_id)
def create_personal_repo_group(self, user_id): """ Create personal repository group for this user :param user_id: """ from rhodecode.model.repo_group import RepoGroupModel user_id = safe_int(user_id) c.user = User.get_or_404(user_id) try: desc = RepoGroupModel.PERSONAL_GROUP_DESC % { 'username': c.user.username } if not RepoGroup.get_by_group_name(c.user.username): RepoGroupModel().create(group_name=c.user.username, group_description=desc, owner=c.user.username) msg = _('Created repository group `%s`' % (c.user.username, )) h.flash(msg, category='success') except Exception: log.exception("Exception during repository group creation") msg = _( 'An error occurred during repository group creation for user') h.flash(msg, category='error') return redirect(url('edit_user_advanced', user_id=user_id))
def test_api_get_repo_group(self, user_util): repo_group = user_util.create_repo_group() repo_group_name = repo_group.group_name id_, params = build_data(self.apikey, 'get_repo_group', repogroupid=repo_group_name) response = api_call(self.app, params) repo_group = RepoGroupModel()._get_repo_group(repo_group_name) ret = repo_group.get_api_data() permissions = expected_permissions(repo_group) ret['members'] = permissions expected = ret assert_ok(id_, expected, given=response.body)
def delete(self, group_name): """DELETE /repo_groups/group_name: Delete an existing item""" # Forms posted to this method should contain a hidden field: # <input type="hidden" name="_method" value="DELETE" /> # Or using helpers: # h.form(url('repos_group', group_name=GROUP_NAME), method='delete') # url('repo_group_home', group_name=GROUP_NAME) gr = c.repo_group = RepoGroupModel()._get_repo_group(group_name) repos = gr.repositories.all() if repos: msg = ungettext( 'This group contains %(num)d repository and cannot be deleted', 'This group contains %(num)d repositories and cannot be' ' deleted', len(repos)) % { 'num': len(repos) } h.flash(msg, category='warning') return redirect(url('repo_groups')) children = gr.children.all() if children: msg = ungettext( 'This group contains %(num)d subgroup and cannot be deleted', 'This group contains %(num)d subgroups and cannot be deleted', len(children)) % { 'num': len(children) } h.flash(msg, category='warning') return redirect(url('repo_groups')) try: RepoGroupModel().delete(group_name) Session().commit() h.flash(_('Removed repository group %s') % group_name, category='success') # TODO: in future action_logger(, '', '', '', self.sa) except Exception: log.exception("Exception during deletion of repository group") h.flash( _('Error occurred during deletion of repository group %s') % group_name, category='error') return redirect(url('repo_groups'))
def cleanup(self): if hasattr(self, 'test_repo'): RepoModel().delete(repo=self.test_repo) if hasattr(self, 'g1'): RepoGroupModel().delete(self.g1.group_id) if hasattr(self, 'g2'): RepoGroupModel().delete(self.g2.group_id) UserModel().delete(self.u1) UserModel().delete(self.u2) UserModel().delete(self.u3) UserModel().delete(self.a1) if hasattr(self, 'ug1'): UserGroupModel().delete(self.ug1, force=True) Session().commit()
def test_user_delete_cascades_permissions_on_repo_group( test_repo_group, test_user): RepoGroupModel().grant_user_permission(test_repo_group, test_user, 'group.write') Session().commit() assert test_user.repo_group_to_perm Session().delete(test_user) Session().commit()
def test_create(self): self.log_user() repo_group_name = self.NEW_REPO_GROUP repo_group_name_unicode = repo_group_name.decode('utf8') description = 'description for newly created repo group' response = self.app.post( url('repo_groups'), fixture._get_group_create_params(group_name=repo_group_name, group_description=description, csrf_token=self.csrf_token)) # run the check page that triggers the flash message # response = self.app.get(url('repo_check_home', repo_name=repo_name)) # assert response.json == {u'result': True} assert_session_flash( response, u'Created repository group <a href="%s">%s</a>' % (h.url('repo_group_home', group_name=repo_group_name), repo_group_name_unicode)) # # test if the repo group was created in the database new_repo_group = RepoGroupModel()._get_repo_group( repo_group_name_unicode) assert new_repo_group is not None assert new_repo_group.group_name == repo_group_name_unicode assert new_repo_group.group_description == description # # # test if the repository is visible in the list ? response = self.app.get( url('repo_group_home', group_name=repo_group_name)) response.mustcontain(repo_group_name) # test if the repository group was created on filesystem is_on_filesystem = os.path.isdir( os.path.join(TESTS_TMP_PATH, repo_group_name)) if not is_on_filesystem: self.fail('no repo group %s in filesystem' % repo_group_name) RepoGroupModel().delete(repo_group_name_unicode) Session().commit()
def index(self): """GET /repo_groups: All items in the collection""" # url('repo_groups') repo_group_list = RepoGroup.get_all_repo_groups() _perms = ['group.admin'] repo_group_list_acl = RepoGroupList(repo_group_list, perm_set=_perms) repo_group_data = RepoGroupModel().get_repo_groups_as_dict( repo_group_list=repo_group_list_acl, admin=True) c.data = json.dumps(repo_group_data) return render('admin/repo_groups/repo_groups.html')
def test_api_get_repo_groups(self): id_, params = build_data(self.apikey, 'get_repo_groups') response = api_call(self.app, params) result = [] for repo in RepoGroupModel().get_all(): result.append(repo.get_api_data()) ret = jsonify(result) expected = ret assert_ok(id_, expected, given=response.body)
def delete_repo_group(request, apiuser, repogroupid): """ Deletes a |repo| group. :param apiuser: This is filled automatically from the |authtoken|. :type apiuser: AuthUser :param repogroupid: Set the name or ID of repository group to be deleted. :type repogroupid: str or int Example output: .. code-block:: bash id : <id_given_in_input> result : { 'msg': 'deleted repo group ID:<repogroupid> <repogroupname> 'repo_group': null } error : null Example error output: .. code-block:: bash id : <id_given_in_input> result : null error : { "failed to delete repo group ID:<repogroupid> <repogroupname>" } """ repo_group = get_repo_group_or_error(repogroupid) if not has_superadmin_permission(apiuser): # check if we have admin permission for this repo group ! _perms = ('group.admin',) if not HasRepoGroupPermissionAnyApi(*_perms)( user=apiuser, group_name=repo_group.group_name): raise JSONRPCError( 'repository group `%s` does not exist' % (repogroupid,)) try: RepoGroupModel().delete(repo_group) Session().commit() return { 'msg': 'deleted repo group ID:%s %s' % (repo_group.group_id, repo_group.group_name), 'repo_group': None } except Exception: log.exception("Exception occurred while trying to delete repo group") raise JSONRPCError('failed to delete repo group ID:%s %s' % (repo_group.group_id, repo_group.group_name))
def _destroy_project_tree(test_u1_id): Session.remove() repo_group = RepoGroup.get_by_group_name(group_name='g0') for el in reversed(repo_group.recursive_groups_and_repos()): if isinstance(el, Repository): RepoModel().delete(el) elif isinstance(el, RepoGroup): RepoGroupModel().delete(el, force_delete=True) u = User.get(test_u1_id) Session().delete(u) Session().commit()
def test_repo_group_user_as_user_group_member(self): # create Group1 self.g1 = fixture.create_repo_group('group1', skip_if_exists=True) assert group_perms(self.anon) == {u'group1': u'group.read'} # set default permission to none RepoGroupModel().grant_user_permission(repo_group=self.g1, user=self.anon, perm='group.none') # make group self.ug1 = fixture.create_user_group('G1') # add user to group UserGroupModel().add_user_to_group(self.ug1, self.u1) Session().commit() # check if user is in the group ug1 = UserGroupModel().get(self.ug1.users_group_id) members = [x.user_id for x in ug1.members] assert members == [self.u1.user_id] # add some user to that group # check his permissions assert group_perms(self.anon) == {u'group1': u'group.none'} assert group_perms(self.u1) == {u'group1': u'group.none'} # grant ug1 read permissions for RepoGroupModel().grant_user_group_permission(repo_group=self.g1, group_name=self.ug1, perm='group.read') Session().commit() # check if the obj = Session().query(UserGroupRepoGroupToPerm)\ .filter(UserGroupRepoGroupToPerm.group == self.g1)\ .filter(UserGroupRepoGroupToPerm.users_group == self.ug1)\ .scalar() assert obj.permission.permission_name == 'group.read' assert group_perms(self.anon) == {u'group1': u'group.none'} assert group_perms(self.u1) == {u'group1': u'group.read'}
def map_groups(path): """ Given a full path to a repository, create all nested groups that this repo is inside. This function creates parent-child relationships between groups and creates default perms for all new groups. :param paths: full path to repository """ from rhodecode.model.repo_group import RepoGroupModel sa = meta.Session() groups = path.split(Repository.NAME_SEP) parent = None group = None # last element is repo in nested groups structure groups = groups[:-1] rgm = RepoGroupModel(sa) owner = User.get_first_super_admin() for lvl, group_name in enumerate(groups): group_name = '/'.join(groups[:lvl] + [group_name]) group = RepoGroup.get_by_group_name(group_name) desc = '%s group' % group_name # skip folders that are now removed repos if REMOVED_REPO_PAT.match(group_name): break if group is None: log.debug('creating group level: %s group_name: %s', lvl, group_name) group = RepoGroup(group_name, parent) group.group_description = desc group.user = owner sa.add(group) perm_obj = rgm._create_default_perms(group) sa.add(perm_obj) sa.flush() parent = group return group
def get_repo_group_or_error(repogroupid): """ Get repo group by id or name or return JsonRPCError if not found :param repogroupid: """ from rhodecode.model.repo_group import RepoGroupModel repo_group = RepoGroupModel()._get_repo_group(repogroupid) if repo_group is None: raise JSONRPCError('repository group `%s` does not exist' % (repogroupid, )) return repo_group
def edit_repo_group_perms(self, group_name): """GET /repo_groups/group_name/edit: Form to edit an existing item""" # url('edit_repo_group', group_name=GROUP_NAME) c.active = 'perms' c.repo_group = RepoGroupModel()._get_repo_group(group_name) self.__load_defaults() defaults = self.__load_data(c.repo_group.group_id) return htmlfill.render( render('admin/repo_groups/repo_group_edit.html'), defaults=defaults, encoding="UTF-8", force_defaults=False)
def test_repo_group_owner_permissions_not_overwritten_by_others(self): # "u1" shall be owner without any special permission assigned self.g1 = fixture.create_repo_group('test1') RepoGroupModel().grant_user_permission(repo_group=self.g1, user=self.u1, perm='group.write') # Verify that user does not get any special permission if he is not # owner assert group_perms(self.u1) == {'test1': 'group.write'} # Make him owner of the repo group self.g1.user = self.u1 assert group_perms(self.u1) == {u'test1': 'group.admin'}
def test_ValidRepoName(): validator = v.ValidRepoName() pytest.raises( formencode.Invalid, validator.to_python, {'repo_name': ''}) pytest.raises( formencode.Invalid, validator.to_python, {'repo_name': HG_REPO}) gr = RepoGroupModel().create(group_name='group_test', group_description='desc', owner=TEST_USER_ADMIN_LOGIN) pytest.raises( formencode.Invalid, validator.to_python, {'repo_name': gr.group_name})
def create_repo_group(self, name, **kwargs): if 'skip_if_exists' in kwargs: del kwargs['skip_if_exists'] gr = RepoGroup.get_by_group_name(group_name=name) if gr: return gr form_data = self._get_group_create_params(group_name=name, **kwargs) owner = kwargs.get('cur_user', TEST_USER_ADMIN_LOGIN) gr = RepoGroupModel().create( group_name=form_data['group_name'], group_description=form_data['group_name'], owner=owner) Session().commit() gr = RepoGroup.get_by_group_name(gr.group_name) return gr
def permissions_setup_func_orig(group_name='g0', perm='group.read', recursive='all'): """ Resets all permissions to perm attribute """ repo_group = RepoGroup.get_by_group_name(group_name=group_name) if not repo_group: raise Exception('Cannot get group %s' % group_name) perm_updates = [[test_u2_gr_id, perm, 'users_group']] RepoGroupModel().update_permissions(repo_group, perm_updates=perm_updates, recursive=recursive, check_perms=False) Session().commit()
def fixup_groups(self): def_usr = User.get_default_user() for g in RepoGroup.query().all(): g.group_name = g.get_new_name(g.name) self.sa.add(g) # get default perm default = UserRepoGroupToPerm.query()\ .filter(UserRepoGroupToPerm.group == g)\ .filter(UserRepoGroupToPerm.user == def_usr)\ .scalar() if default is None: log.debug('missing default permission for group %s adding' % g) perm_obj = RepoGroupModel()._create_default_perms(g) self.sa.add(perm_obj)