From 3a016c244187140ec4973eeffcf2fd7a04b4a772 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Oct 10 2017 13:29:34 +0000 Subject: Add to pagure-admin the actions: read-only This action allows to get or set the read-only status of a project. With its corresponding unit-tests Signed-off-by: Pierre-Yves Chibon Signed-off-by: Pierre-Yves Chibon --- diff --git a/pagure/cli/admin.py b/pagure/cli/admin.py index 52da23d..5411d77 100644 --- a/pagure/cli/admin.py +++ b/pagure/cli/admin.py @@ -166,6 +166,22 @@ def _parser_update_watch(subparser): local_parser.set_defaults(func=do_update_watch_status) +def _parser_read_only(subparser): + """ Set up the CLI argument parser for the refresh-gitolite action. """ + local_parser = subparser.add_parser( + 'read-only', + help='Get or set the read-only flag on a project') + local_parser.add_argument( + '--user', help="User of the project (to use only on forks)") + local_parser.add_argument( + 'project', help="Project to update (as namespace/project if there " + "is a namespace)") + local_parser.add_argument( + '--ro', + help="Read-Only status to set (has to be: true or false), do not " + "specify to get the current status") + local_parser.set_defaults(func=do_read_only) + def parse_arguments(): """ Set-up the argument parsing. """ parser = argparse.ArgumentParser( @@ -195,6 +211,9 @@ def parse_arguments(): # update-watch _parser_update_watch(subparser) + # read-only + _parser_read_only(subparser) + return parser.parse_args() @@ -486,6 +505,47 @@ def do_update_watch_status(args): SESSION.commit() +def do_read_only(args): + """ Set or update the read-only status of a project. + + :arg args: the argparse object returned by ``parse_arguments()``. + + """ + + _log.debug('project: %s', args.project) + _log.debug('user: %s', args.user) + _log.debug('read-only: %s', args.ro) + + # Validate user + pagure.lib.get_user(SESSION, args.user) + + # Get the project + project = _get_project(args.project) + + if project is None: + raise pagure.exceptions.PagureException( + 'No project found with: %s' % args.project) + + # Validate ro flag + if args.ro and args.ro.lower() not in ['true', 'false']: + raise pagure.exceptions.PagureException( + 'Invalid read-only status specified: %s is not in: ' + 'true, false' % args.ro.lower()) + + if not args.ro: + print( + 'The current read-only flag of the project %s is set to %s' % ( + project.fullname, project.read_only)) + else: + pagure.lib.update_read_only_mode( + SESSION, project, read_only=(args.ro.lower() == 'true') + ) + SESSION.commit() + print( + 'The read-only flag of the project %s has been set to %s' % ( + project.fullname, args.ro.lower() == 'true')) + + def main(): """ Start of the application. """ diff --git a/tests/test_pagure_admin.py b/tests/test_pagure_admin.py index 2f32a54..acd98f6 100644 --- a/tests/test_pagure_admin.py +++ b/tests/test_pagure_admin.py @@ -64,7 +64,7 @@ class PagureAdminHelptests(tests.Modeltests): output = _get_ouput(cmd) self.assertEqual(output[0], '') self.assertEqual(output[1], '''usage: admin.py [-h] [--debug] - {refresh-gitolite,refresh-ssh,clear-hook-token,admin-token,get-watch,update-watch} + {refresh-gitolite,refresh-ssh,clear-hook-token,admin-token,get-watch,update-watch,read-only} ... admin.py: error: too few arguments ''') # noqa @@ -75,7 +75,7 @@ admin.py: error: too few arguments self.assertEqual( _get_ouput(cmd)[0], '''usage: admin.py [-h] [--debug] - {refresh-gitolite,refresh-ssh,clear-hook-token,admin-token,get-watch,update-watch} + {refresh-gitolite,refresh-ssh,clear-hook-token,admin-token,get-watch,update-watch,read-only} ... The admin CLI for this pagure instance @@ -85,7 +85,7 @@ optional arguments: --debug Increase the verbosity of the information displayed actions: - {refresh-gitolite,refresh-ssh,clear-hook-token,admin-token,get-watch,update-watch} + {refresh-gitolite,refresh-ssh,clear-hook-token,admin-token,get-watch,update-watch,read-only} refresh-gitolite Re-generate the gitolite config file refresh-ssh Re-write to disk every user's ssh key stored in the database @@ -94,6 +94,7 @@ actions: admin-token Manages the admin tokens for this instance get-watch Get someone's watch status on a project update-watch Update someone's watch status on a project + read-only Get or set the read-only flag on a project ''') def test_parser_refresh_gitolite_help(self): @@ -257,6 +258,25 @@ optional arguments: Watch status to update to ''') + def test_parser_read_only(self): + """ Test the _parser_update_watch function of pagure-admin. """ + cmd = ['python', PAGURE_ADMIN, 'read-only', '--help'] + print _get_ouput(cmd)[0] + self.assertEqual( + _get_ouput(cmd)[0], + '''usage: admin.py read-only [-h] [--user USER] [--ro RO] project + +positional arguments: + project Project to update (as namespace/project if there is a + namespace) + +optional arguments: + -h, --help show this help message and exit + --user USER User of the project (to use only on forks) + --ro RO Read-Only status to set (has to be: true or false), do not + specify to get the current status +''') + class PagureAdminAdminTokenEmptytests(tests.Modeltests): """ Tests for pagure-admin admin-token when there is nothing in the DB @@ -882,5 +902,165 @@ class PagureAdminUpdateWatchTests(tests.Modeltests): 'issues, pull-requests\n', output) +class PagureAdminReadOnlyTests(tests.Modeltests): + """ Tests for pagure-admin read-only """ + + def setUp(self): + """ Set up the environnment, ran before every tests. """ + super(PagureAdminReadOnlyTests, self).setUp() + + self.configfile = os.path.join(self.path, 'config') + self.dbpath = "sqlite:///%s/pagure_dev.sqlite" % self.path + with open(self.configfile, 'w') as stream: + stream.write('DB_URL="%s"\n' % self.dbpath) + + os.environ['PAGURE_CONFIG'] = self.configfile + + createdb = os.path.abspath( + os.path.join(tests.HERE, '..', 'createdb.py')) + cmd = ['python', createdb] + _get_ouput(cmd) + + self.session = pagure.lib.model.create_tables( + self.dbpath, acls=pagure.APP.config.get('ACLS', {})) + + # Create the user pingou + item = pagure.lib.model.User( + user='pingou', + fullname='PY C', + password='foo', + default_email='bar@pingou.com', + ) + self.session.add(item) + item = pagure.lib.model.UserEmail( + user_id=1, + email='bar@pingou.com') + self.session.add(item) + + # Create two projects for the user pingou + item = pagure.lib.model.Project( + user_id=1, # pingou + name='test', + description='namespaced test project', + hook_token='aaabbbeee', + namespace='somenamespace', + ) + self.session.add(item) + + item = pagure.lib.model.Project( + user_id=1, # pingou + name='test', + description='Test project', + hook_token='aaabbbccc', + namespace=None, + ) + self.session.add(item) + + self.session.commit() + + # Make the imported pagure use the correct db session + pagure.cli.admin.SESSION = self.session + + def tearDown(self): + """ Tear down the environnment after running the tests. """ + super(PagureAdminReadOnlyTests, self).tearDown() + del(os.environ['PAGURE_CONFIG']) + + def test_read_only_unknown_project(self): + """ Test the read-only function of pagure-admin on an unknown + project. + """ + + cmd = ['python', PAGURE_ADMIN, 'read-only', 'foob'] + output = _get_ouput(cmd)[0] + self.assertEqual('No project found with: foob\n', output) + + def test_read_only_invalid_project(self): + """ Test the read-only function of pagure-admin on an invalid + project. + """ + + cmd = ['python', PAGURE_ADMIN, 'read-only', 'fo/o/b'] + output = _get_ouput(cmd)[0] + self.assertEqual( + 'Invalid project name, has more than one "/": fo/o/b\n', + output) + + def test_read_only(self): + """ Test the read-only function of pagure-admin to get status of + a non-namespaced project. + """ + + cmd = ['python', PAGURE_ADMIN, 'read-only', 'test'] + output = _get_ouput(cmd)[0] + self.assertEqual( + 'The current read-only flag of the project test is set to True\n', + output) + + def test_read_only_namespace(self): + """ Test the read-only function of pagure-admin to get status of + a namespaced project. + """ + + cmd = ['python', PAGURE_ADMIN, 'read-only', 'somenamespace/test'] + output = _get_ouput(cmd)[0] + self.assertEqual( + 'The current read-only flag of the project somenamespace/test '\ + 'is set to True\n', output) + + def test_read_only_namespace_changed(self): + """ Test the read-only function of pagure-admin to set the status of + a namespaced project. + """ + + # Before + cmd = ['python', PAGURE_ADMIN, 'read-only', 'somenamespace/test'] + output = _get_ouput(cmd)[0] + self.assertEqual( + 'The current read-only flag of the project somenamespace/test '\ + 'is set to True\n', output) + + cmd = [ + 'python', PAGURE_ADMIN, 'read-only', + 'somenamespace/test', '--ro', 'false'] + output = _get_ouput(cmd)[0] + self.assertEqual( + 'The read-only flag of the project somenamespace/test has been ' + 'set to False\n', output) + + # After + cmd = ['python', PAGURE_ADMIN, 'read-only', 'somenamespace/test'] + output = _get_ouput(cmd)[0] + self.assertEqual( + 'The current read-only flag of the project somenamespace/test '\ + 'is set to False\n', output) + + def test_read_only_no_change(self): + """ Test the read-only function of pagure-admin to set the status of + a namespaced project. + """ + + # Before + cmd = ['python', PAGURE_ADMIN, 'read-only', 'test'] + output = _get_ouput(cmd)[0] + self.assertEqual( + 'The current read-only flag of the project test '\ + 'is set to True\n', output) + + cmd = [ + 'python', PAGURE_ADMIN, 'read-only', 'test', '--ro', 'true'] + output = _get_ouput(cmd)[0] + self.assertEqual( + 'The read-only flag of the project test has been ' + 'set to True\n', output) + + # After + cmd = ['python', PAGURE_ADMIN, 'read-only', 'test'] + output = _get_ouput(cmd)[0] + self.assertEqual( + 'The current read-only flag of the project test '\ + 'is set to True\n', output) + + if __name__ == '__main__': unittest.main(verbosity=2)