diff --git a/doc/configuration.rst b/doc/configuration.rst index 4c6a666..46782fb 100644 --- a/doc/configuration.rst +++ b/doc/configuration.rst @@ -604,6 +604,24 @@ this pagure instance does not have a documentation server. Defaults to: ``None`` +EXCLUDE_GROUP_INDEX +~~~~~~~~~~~~~~~~~~~ + +This configuration key can be used to hide project an user has access to via +one of the groups listed in this key. + +The use-case is the following: the Fedora project is deploying pagure has a +front-end for the git repos of the packages in the distribution, that means +about 17,000 git repositories in pagure. The project has a group of people +that have access to all of these repositories, so when viewing the user's +page of one member ot that group, instead of seeing all the project that +this user works on, you can see all the projects hosted in that pagure +instance. Using this configuration key, pagure will hide all the projects +that this user has access to via the specified groups and thus return only +the groups of forks of that users. + +Defaults to: ``[]`` + Deprecated configuration keys ----------------------------- diff --git a/pagure/default_config.py b/pagure/default_config.py index 658b27a..3d9a780 100644 --- a/pagure/default_config.py +++ b/pagure/default_config.py @@ -232,3 +232,7 @@ PAGURE_CI_SERVICES = [] # Boolean to turn on project being by default in the user's namespace USER_NAMESPACE = False + +# List of groups whose projects should not be shown on the user's info page +# unless the user has direct access to it. +EXCLUDE_GROUP_INDEX = [] diff --git a/pagure/lib/__init__.py b/pagure/lib/__init__.py index dd0c511..c5fac38 100644 --- a/pagure/lib/__init__.py +++ b/pagure/lib/__init__.py @@ -1685,7 +1685,8 @@ def fork_project(session, user, repo, gitfolder, def search_projects( session, username=None, fork=None, tags=None, namespace=None, pattern=None, - start=None, limit=None, count=False, sort=None): + start=None, limit=None, count=False, sort=None, + exclude_groups=None): '''List existing projects ''' projects = session.query( @@ -1736,6 +1737,16 @@ def search_projects( ) ) + # Exclude projects that the user has accessed via a group that we + # do not want to include + if exclude_groups: + sub_q3 = sub_q3.filter( + model.PagureGroup.group_name.notin_(exclude_groups) + ) + sub_q4 = sub_q4.filter( + model.PagureGroup.group_name.notin_(exclude_groups) + ) + projects = projects.union(sub_q2).union(sub_q3).union(sub_q4) if fork is not None: diff --git a/pagure/ui/app.py b/pagure/ui/app.py index 302e70b..a7b0920 100644 --- a/pagure/ui/app.py +++ b/pagure/ui/app.py @@ -95,6 +95,7 @@ def index_auth(): repos = pagure.lib.search_projects( SESSION, username=flask.g.fas_user.username, + exclude_groups=APP.config.get('EXCLUDE_GROUP_INDEX'), fork=False) repos_length = pagure.lib.search_projects( SESSION, @@ -298,6 +299,7 @@ def view_user(username): SESSION, username=username, fork=False, + exclude_groups=APP.config.get('EXCLUDE_GROUP_INDEX'), start=repo_start, limit=limit) repos_length = pagure.lib.search_projects( diff --git a/tests/test_pagure_exclude_group_index.py b/tests/test_pagure_exclude_group_index.py new file mode 100644 index 0000000..295de5a --- /dev/null +++ b/tests/test_pagure_exclude_group_index.py @@ -0,0 +1,175 @@ +# -*- coding: utf-8 -*- + +""" + (c) 2017 - Copyright Red Hat Inc + + Authors: + Pierre-Yves Chibon + +""" + +__requires__ = ['SQLAlchemy >= 0.8'] +import pkg_resources + +import unittest +import shutil +import sys +import os + +import mock + +sys.path.insert(0, os.path.join(os.path.dirname( + os.path.abspath(__file__)), '..')) + +import pagure.lib +import pagure.lib.model +import tests + +class PagureExcludeGroupIndex(tests.Modeltests): + """ Tests the EXCLUDE_GROUP_INDEX configuration key in pagure """ + + def setUp(self): + """ Set up the environnment, ran before every tests. """ + super(PagureExcludeGroupIndex, self).setUp() + + pagure.APP.config['GIT_FOLDER'] = os.path.join(self.path, 'repos') + tests.create_projects(self.session) + tests.create_projects_git(os.path.join(self.path, 'repos'), bare=True) + + # Create a ``provenpackger`` group: + msg = pagure.lib.add_group( + self.session, + group_name='provenpackager', + display_name='Proven Packagers', + description='Packagers having access to all the repo', + group_type='user', + user='pingou', + is_admin=False, + blacklist=[], + ) + self.session.commit() + self.assertEqual( + msg, 'User `pingou` added to the group `provenpackager`.') + + # Add the `provenpackager` group to the test2 project + project = pagure.lib.get_project(self.session, 'test2') + msg = pagure.lib.add_group_to_project( + session=self.session, + project=project, + new_group='provenpackager', + user='pingou', + ) + self.session.commit() + self.assertEqual(msg, 'Group added') + + def test_defaults_pingou(self): + """ Test which repo pingou has by default. """ + + repos = pagure.lib.search_projects( + self.session, + username='pingou', + fork=False, + ) + + self.assertEqual(len(repos), 3) + for idx, name in enumerate(['test', 'test2', 'test3']): + self.assertEqual(repos[idx].name, name) + + def test_defaults_foo(self): + """ Test which repo foo has by default. """ + + repos = pagure.lib.search_projects( + self.session, + username='foo', + fork=False, + ) + + self.assertEqual(len(repos), 0) + + + def test_add_foo_test(self): + """ Test adding foo to the test project. """ + + group = pagure.lib.search_groups( + self.session, group_name='provenpackager') + self.assertEqual(group.group_name, 'provenpackager') + + # List all foo's project before (ie: there should be none) + repos = pagure.lib.search_projects( + self.session, + username='foo', + fork=False, + ) + + self.assertEqual(len(repos), 0) + + # Adding `foo` to the `provenpackager` group + msg = pagure.lib.add_user_to_group( + self.session, + username='foo', + group=group, + user='pingou', + is_admin=False, + ) + self.assertEqual( + msg, 'User `foo` added to the group `provenpackager`.') + + # Test that foo has now one project, via the provenpackager group + repos = pagure.lib.search_projects( + self.session, + username='foo', + fork=False, + ) + + self.assertEqual(len(repos), 1) + self.assertEqual(repos[0].name, 'test2') + + def test_excluding_provenpackager(self): + """ Test retrieving user's repo with a group excluded. """ + + # Add `foo` to `provenpackager` + group = pagure.lib.search_groups( + self.session, group_name='provenpackager') + self.assertEqual(group.group_name, 'provenpackager') + + msg = pagure.lib.add_user_to_group( + self.session, + username='foo', + group=group, + user='pingou', + is_admin=False, + ) + self.assertEqual( + msg, 'User `foo` added to the group `provenpackager`.') + + # Get foo's project outside of proven packager + repos = pagure.lib.search_projects( + self.session, + username='foo', + exclude_groups=['provenpackager'], + fork=False, + ) + + self.assertEqual(len(repos), 0) + + # Get pingou's project outside of proven packager (nothing changes) + repos = pagure.lib.search_projects( + self.session, + username='pingou', + exclude_groups=['provenpackager'], + fork=False, + ) + repos2 = pagure.lib.search_projects( + self.session, + username='pingou', + fork=False, + ) + + self.assertEqual(repos, repos2) + self.assertEqual(len(repos), 3) + for idx, name in enumerate(['test', 'test2', 'test3']): + self.assertEqual(repos[idx].name, name) + + +if __name__ == '__main__': + unittest.main(verbosity=2)