From af51847d8992e1e9f89a95c2d85df571d0ba79e0 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Mar 22 2017 08:57:29 +0000 Subject: [PATCH 1/6] Add support for admin API token to pagure-admin --- diff --git a/pagure/cli/admin.py b/pagure/cli/admin.py index b292e9f..a4280ee 100644 --- a/pagure/cli/admin.py +++ b/pagure/cli/admin.py @@ -10,6 +10,7 @@ from __future__ import print_function import argparse +import datetime import logging import os @@ -21,7 +22,7 @@ if 'PAGURE_CONFIG' not in os.environ \ import pagure.exceptions import pagure.lib import pagure.lib.git -from pagure import (SESSION, generate_user_key_files) +from pagure import (SESSION, APP, generate_user_key_files) _log = logging.getLogger(__name__) @@ -57,6 +58,50 @@ def parse_arguments(): help='Generate a new hook token for every project in this instance') parser_hook_token.set_defaults(func=do_generate_hook_token) + # Admin token actions + parser_admin_token = subparsers.add_parser( + 'admin-token', + help='Manages the admin tokens for this instance') + + subsubparsers = parser_admin_token.add_subparsers(title='actions') + + # List admin token + parser_admin_list_token = subsubparsers.add_parser( + 'list', help="List the API admin token") + parser_admin_list_token.add_argument( + '--user', + help="User to associate or associated with the token") + parser_admin_list_token.add_argument( + '--token', help="API token") + parser_admin_list_token.add_argument( + '--active', default=False, action='store_true', + help="Only list active API token") + parser_admin_list_token.add_argument( + '--expired', default=False, action='store_true', + help="Only list expired API token") + parser_admin_token.set_defaults(func=do_list_admin_token) + + # Info about admin token + parser_admin_info_token = subsubparsers.add_parser( + 'info', help="Provide some information about a specific API token") + parser_admin_info_token.add_argument( + 'token', help="API token") + parser_admin_info_token.set_defaults(func=do_info_admin_token) + + # Expire admin token + parser_admin_expire_token = subsubparsers.add_parser( + 'expire', help="Expire a specific API token") + parser_admin_expire_token.add_argument( + 'token', help="API token") + parser_admin_expire_token.set_defaults(func=do_expire_admin_token) + + # Create admin token + parser_admin_create_token = subsubparsers.add_parser( + 'create', help="Create a new API token") + parser_admin_create_token.add_argument( + 'user', help="User to associate with the token") + parser_admin_create_token.set_defaults(func=do_create_admin_token) + return parser.parse_args() @@ -67,7 +112,7 @@ def _ask_confirmation(): return action.lower() in ['y', 'yes'] -def do_generate_acl(): +def do_generate_acl(_): """ Regenerate the gitolite ACL file. """ cmd = pagure.lib.git._get_gitolite_command() if not cmd: @@ -80,7 +125,7 @@ def do_generate_acl(): print('Gitolite ACLs updated') -def do_refresh_ssh(): +def do_refresh_ssh(_): """ Regenerate the user key files. """ print('Do you want to re-generate all the ssh keys for every user in ' 'the database? (Depending on your instance this may take a while ' @@ -101,6 +146,86 @@ def do_generate_hook_token(): print('Hook token all re-generated') +def do_list_admin_token(args): + """ List the admin token. """ + _log.debug('user: %s', args.user) + _log.debug('token: %s', args.token) + _log.debug('active: %s', args.active) + _log.debug('expire: %s', args.expired) + + acls = APP.config['ADMIN_API_ACLS'] + tokens = pagure.lib.search_token( + SESSION, acls, active=args.active, expired=args.expired) + for token in tokens: + print('%s -- %s -- %s' % ( + token.id, token.user.user, token.expiration)) + if not tokens: + print('No admin tokens found') + + +def do_info_admin_token(args): + """ Print out information about the specified API token. """ + _log.debug('token: %s', args.token) + + acls = APP.config['ADMIN_API_ACLS'] + token = pagure.lib.search_token(SESSION, acls, token=args.token) + if not token: + raise pagure.exceptions.PagureException('No such admin token found') + + print('%s -- %s -- %s' % ( + token.id, token.user.user, token.expiration)) + print('ACLs:') + for acl in token.acls: + print(' - %s' % acl.name) + + +def do_expire_admin_token(args): + """ Expire a specific admin token. """ + _log.debug('token: %s', args.token) + + acls = APP.config['ADMIN_API_ACLS'] + token = pagure.lib.search_token(SESSION, acls, token=args.token) + if not token: + raise pagure.exceptions.PagureException('No such admin token found') + + print('%s -- %s -- %s' % ( + token.id, token.user.user, token.expiration)) + print('ACLs:') + for acl in token.acls: + print(' - %s' % acl.name) + + print('Do you really want to expire this API token?') + if _ask_confirmation(): + token.expiration = datetime.datetime.utcnow() + SESSION.add(token) + SESSION.commit() + print('Token expired') + + +def do_create_admin_token(args): + """ Create a new admin token. """ + _log.debug('user: %s', args.user) + # Validate user first + user_obj = pagure.lib.get_user(SESSION, args.user) + + acls_list = APP.config['ADMIN_API_ACLS'] + for idx, acl in enumerate(acls_list): + print('%s. %s' % (idx, acl)) + + print('Which ACLs do you want to associated with this token?') + acls = raw_input('(Conna separated list): ') + acls_idx = [int(acl.strip()) for acl in acls.split(',')] + acls = [acls_list[acl] for acl in acls_idx] + + print('ACLs selected:') + for idx, acl in enumerate(acls_idx): + print('%s. %s' % (acls_idx[idx], acls[idx])) + + print('Do you want to create this API token?') + if _ask_confirmation(): + print(pagure.lib.add_token_to_user(SESSION, None, acls, args.user)) + + def main(): """ Start of the application. """ @@ -114,7 +239,7 @@ def main(): # Act based on the arguments given return_code = 0 try: - args.func() + args.func(args) except KeyboardInterrupt: print("\nInterrupted by user.") return_code = 1 diff --git a/pagure/lib/__init__.py b/pagure/lib/__init__.py index f01dd5f..43ad605 100644 --- a/pagure/lib/__init__.py +++ b/pagure/lib/__init__.py @@ -4218,3 +4218,55 @@ def get_obj_access(session, project_obj, obj): ) return query.first() + + +def search_token( + session, acls, user=None, token=None, active=False, expired=False): + ''' Searches the API tokens corresponding to the criterias specified. + + :arg session: the session to use to connect to the database. + :arg acls: List of the ACL associated with these API tokens + :arg user: restrict the API tokens to this given user + :arg token: restrict the API tokens to this specified token (if it + exists) + ''' + query = session.query( + model.Token + ).filter( + model.Token.id == model.TokenAcl.token_id + ).filter( + model.TokenAcl.acl_id == model.ACL.id + ) + + if isinstance(acls, list): + query = query.filter( + model.ACL.name.in_(acls) + ) + else: + query = query.filter( + model.ACL.name == acls + ) + + if user: + query = query.filter( + model.Token.user_id == model.User.id + ).filter( + model.User.user == user + ) + + if active: + query = query.filter( + model.Token.expiration > datetime.datetime.utcnow() + ) + elif expired: + query = query.filter( + model.Token.expiration <= datetime.datetime.utcnow() + ) + + if token: + query = query.filter( + model.Token.id == token + ) + return query.first() + else: + return query.all() From f4ba432e91b2c663bcd8c8f06f1278eb41c1fde7 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Mar 22 2017 08:57:29 +0000 Subject: [PATCH 2/6] Small flake8 clean up to pagure/cli --- diff --git a/pagure/cli/admin.py b/pagure/cli/admin.py index a4280ee..b6bb983 100644 --- a/pagure/cli/admin.py +++ b/pagure/cli/admin.py @@ -13,16 +13,17 @@ import argparse import datetime import logging import os +import sys if 'PAGURE_CONFIG' not in os.environ \ and os.path.exists('/etc/pagure/pagure.cfg'): print('Using configuration file `/etc/pagure/pagure.cfg`') os.environ['PAGURE_CONFIG'] = '/etc/pagure/pagure.cfg' -import pagure.exceptions -import pagure.lib -import pagure.lib.git -from pagure import (SESSION, APP, generate_user_key_files) +import pagure.exceptions # noqa +import pagure.lib # noqa +import pagure.lib.git # noqa +from pagure import (SESSION, APP, generate_user_key_files) # noqa _log = logging.getLogger(__name__) @@ -36,7 +37,7 @@ def parse_arguments(): parser.add_argument( '--debug', default=False, action='store_true', help='Increase the verbosity of the information displayed') - parser.set_defaults(func=lambda a, k : print(parser.format_help())) + parser.set_defaults(func=lambda a, k: print(parser.format_help())) subparsers = parser.add_subparsers(title='actions') @@ -118,7 +119,8 @@ def do_generate_acl(_): if not cmd: raise pagure.exceptions.PagureException( '/!\ un-able to generate the right gitolite command') - print('Do you want to re-generate the gitolite.conf file then ' + print( + 'Do you want to re-generate the gitolite.conf file then ' 'calling: %s' % cmd) if _ask_confirmation(): pagure.lib.git.generate_gitolite_acls() @@ -127,7 +129,8 @@ def do_generate_acl(_): def do_refresh_ssh(_): """ Regenerate the user key files. """ - print('Do you want to re-generate all the ssh keys for every user in ' + print( + 'Do you want to re-generate all the ssh keys for every user in ' 'the database? (Depending on your instance this may take a while ' 'and result in an outage while it lasts)') if _ask_confirmation(): @@ -138,7 +141,8 @@ def do_refresh_ssh(_): def do_generate_hook_token(): """ Regenerate the hook_token for each projects in the DB. """ - print('Do you want to re-generate all the hook token for every user in ' + print( + 'Do you want to re-generate all the hook token for every user in ' 'the database? This will break every web-hook set-up on this ' 'instance. You should only ever run this for a security issue') if _ask_confirmation(): @@ -206,7 +210,7 @@ def do_create_admin_token(args): """ Create a new admin token. """ _log.debug('user: %s', args.user) # Validate user first - user_obj = pagure.lib.get_user(SESSION, args.user) + pagure.lib.get_user(SESSION, args.user) acls_list = APP.config['ADMIN_API_ACLS'] for idx, acl in enumerate(acls_list): From b22dbfbe85538b7f3b671b09789cebbf30ce7d10 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Mar 22 2017 08:57:29 +0000 Subject: [PATCH 3/6] Improve the docstrings in pagure-admin as advised by @bowlofeggs --- diff --git a/pagure/cli/admin.py b/pagure/cli/admin.py index b6bb983..4dc45f4 100644 --- a/pagure/cli/admin.py +++ b/pagure/cli/admin.py @@ -107,14 +107,20 @@ def parse_arguments(): def _ask_confirmation(): - ''' Ask to confirm an action + ''' Ask to confirm an action. ''' action = raw_input('Do you want to continue? [y/N]') return action.lower() in ['y', 'yes'] def do_generate_acl(_): - """ Regenerate the gitolite ACL file. """ + """ Regenerate the gitolite ACL file. + + + :arg _: the argparse object returned by ``parse_arguments()``, which is + ignored as there are no argument to pass to this action. + + """ cmd = pagure.lib.git._get_gitolite_command() if not cmd: raise pagure.exceptions.PagureException( @@ -128,7 +134,12 @@ def do_generate_acl(_): def do_refresh_ssh(_): - """ Regenerate the user key files. """ + """ Regenerate the user key files. + + :arg _: the argparse object returned by ``parse_arguments()``, which is + ignored as there are no argument to pass to this action. + + """ print( 'Do you want to re-generate all the ssh keys for every user in ' 'the database? (Depending on your instance this may take a while ' @@ -139,8 +150,13 @@ def do_refresh_ssh(_): do_generate_acl() -def do_generate_hook_token(): - """ Regenerate the hook_token for each projects in the DB. """ +def do_generate_hook_token(_): + """ Regenerate the hook_token for each projects in the DB. + + :arg _: the argparse object returned by ``parse_arguments()``, which is + ignored as there are no argument to pass to this action. + + """ print( 'Do you want to re-generate all the hook token for every user in ' 'the database? This will break every web-hook set-up on this ' @@ -151,7 +167,11 @@ def do_generate_hook_token(): def do_list_admin_token(args): - """ List the admin token. """ + """ List the admin token. + + :arg args: the argparse object returned by ``parse_arguments()``. + + """ _log.debug('user: %s', args.user) _log.debug('token: %s', args.token) _log.debug('active: %s', args.active) @@ -168,7 +188,11 @@ def do_list_admin_token(args): def do_info_admin_token(args): - """ Print out information about the specified API token. """ + """ Print out information about the specified API token. + + :arg args: the argparse object returned by ``parse_arguments()``. + + """ _log.debug('token: %s', args.token) acls = APP.config['ADMIN_API_ACLS'] @@ -184,7 +208,11 @@ def do_info_admin_token(args): def do_expire_admin_token(args): - """ Expire a specific admin token. """ + """ Expire a specific admin token. + + :arg args: the argparse object returned by ``parse_arguments()``. + + """ _log.debug('token: %s', args.token) acls = APP.config['ADMIN_API_ACLS'] @@ -207,7 +235,11 @@ def do_expire_admin_token(args): def do_create_admin_token(args): - """ Create a new admin token. """ + """ Create a new admin token. + + :arg args: the argparse object returned by ``parse_arguments()``. + + """ _log.debug('user: %s', args.user) # Validate user first pagure.lib.get_user(SESSION, args.user) From 6bf2587f01baa963fc77be5a7e62ecc4c46b42a0 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Mar 22 2017 08:57:29 +0000 Subject: [PATCH 4/6] Restructure how the argument parsing is done as advised by @bowlofeggs --- diff --git a/pagure/cli/admin.py b/pagure/cli/admin.py index 4dc45f4..e9994c4 100644 --- a/pagure/cli/admin.py +++ b/pagure/cli/admin.py @@ -29,79 +29,118 @@ from pagure import (SESSION, APP, generate_user_key_files) # noqa _log = logging.getLogger(__name__) -def parse_arguments(): - """ Set-up the argument parsing. """ - parser = argparse.ArgumentParser( - description='The admin CLI for this pagure instance') - - parser.add_argument( - '--debug', default=False, action='store_true', - help='Increase the verbosity of the information displayed') - parser.set_defaults(func=lambda a, k: print(parser.format_help())) - - subparsers = parser.add_subparsers(title='actions') - - # refresh-gitolite - parser_gitolite = subparsers.add_parser( +def _parser_refresh_gitolite(subparser): + """ Set up the CLI argument parser for the refresh-gitolite action. """ + local_parser = subparser.add_parser( 'refresh-gitolite', help='Re-generate the gitolite config file') - parser_gitolite.set_defaults(func=do_generate_acl) + local_parser.set_defaults(func=do_generate_acl) - # refresh-ssh - parser_ssh = subparsers.add_parser( + +def _parser_refresh_ssh(subparser): + """ Set up the CLI argument parser for the refresh-ssh action. """ + local_parser = subparser.add_parser( 'refresh-ssh', help="Re-write to disk every user's ssh key stored in the database") - parser_ssh.set_defaults(func=do_refresh_ssh) + local_parser.set_defaults(func=do_refresh_ssh) - # clear-hook-token - parser_hook_token = subparsers.add_parser( + +def _parser_clear_hook_token(subparser): + """ Set up the CLI argument parser for the clear-hook-token action. """ + local_parser = subparser.add_parser( 'clear-hook-token', help='Generate a new hook token for every project in this instance') - parser_hook_token.set_defaults(func=do_generate_hook_token) - - # Admin token actions - parser_admin_token = subparsers.add_parser( - 'admin-token', - help='Manages the admin tokens for this instance') + local_parser.set_defaults(func=do_generate_hook_token) - subsubparsers = parser_admin_token.add_subparsers(title='actions') - # List admin token - parser_admin_list_token = subsubparsers.add_parser( +def _parser_admin_token_list(subparser): + """ Set up the CLI argument parser for the admin-token list action. """ + local_parser = subparser.add_parser( 'list', help="List the API admin token") - parser_admin_list_token.add_argument( + local_parser.add_argument( '--user', help="User to associate or associated with the token") - parser_admin_list_token.add_argument( + local_parser.add_argument( '--token', help="API token") - parser_admin_list_token.add_argument( + local_parser.add_argument( '--active', default=False, action='store_true', help="Only list active API token") - parser_admin_list_token.add_argument( + local_parser.add_argument( '--expired', default=False, action='store_true', help="Only list expired API token") - parser_admin_token.set_defaults(func=do_list_admin_token) + local_parser.set_defaults(func=do_list_admin_token) + - # Info about admin token - parser_admin_info_token = subsubparsers.add_parser( +def _parser_admin_token_info(subparser): + """ Set up the CLI argument parser for the admin-token info action. """ + local_parser = subparser.add_parser( 'info', help="Provide some information about a specific API token") - parser_admin_info_token.add_argument( + local_parser.add_argument( 'token', help="API token") - parser_admin_info_token.set_defaults(func=do_info_admin_token) + local_parser.set_defaults(func=do_info_admin_token) + +def _parser_admin_token_expire(subparser): + """ Set up the CLI argument parser for the admin-token expire action. """ # Expire admin token - parser_admin_expire_token = subsubparsers.add_parser( + local_parser = subparser.add_parser( 'expire', help="Expire a specific API token") - parser_admin_expire_token.add_argument( + local_parser.add_argument( 'token', help="API token") - parser_admin_expire_token.set_defaults(func=do_expire_admin_token) + local_parser.set_defaults(func=do_expire_admin_token) + +def _parser_admin_token_create(subparser): + """ Set up the CLI argument parser for the admin-token create action. """ # Create admin token - parser_admin_create_token = subsubparsers.add_parser( + local_parser = subparser.add_parser( 'create', help="Create a new API token") - parser_admin_create_token.add_argument( + local_parser.add_argument( 'user', help="User to associate with the token") - parser_admin_create_token.set_defaults(func=do_create_admin_token) + local_parser.set_defaults(func=do_create_admin_token) + + +def _parser_admin_token(subparser): + """ Set up the CLI argument parser for the admin-token action. """ + local_parser = subparser.add_parser( + 'admin-token', + help='Manages the admin tokens for this instance') + + subsubparser = local_parser.add_subparsers(title='actions') + + # list + _parser_admin_token_list(subsubparser) + # info + _parser_admin_token_info(subsubparser) + # expire + _parser_admin_token_expire(subsubparser) + # create + _parser_admin_token_create(subsubparser) + + +def parse_arguments(): + """ Set-up the argument parsing. """ + parser = argparse.ArgumentParser( + description='The admin CLI for this pagure instance') + + parser.add_argument( + '--debug', default=False, action='store_true', + help='Increase the verbosity of the information displayed') + parser.set_defaults(func=lambda a, k: print(parser.format_help())) + + subparser = parser.add_subparsers(title='actions') + + # refresh-gitolite + _parser_refresh_gitolite(subparser) + + # refresh-ssh + _parser_refresh_ssh(subparser) + + # clear-hook-token + _parser_clear_hook_token(subparser) + + # Admin token actions + _parser_admin_token(subparser) return parser.parse_args() From 12c3d1fe5f6b441badd0c35214fe9e6deff21632 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Mar 22 2017 08:57:29 +0000 Subject: [PATCH 5/6] Wrap the raw_input into its own method so we can easily patch it for our tests --- diff --git a/pagure/cli/admin.py b/pagure/cli/admin.py index e9994c4..2c43e3a 100644 --- a/pagure/cli/admin.py +++ b/pagure/cli/admin.py @@ -152,6 +152,11 @@ def _ask_confirmation(): return action.lower() in ['y', 'yes'] +def _get_input(text): + ''' Ask the user for input. ''' + return raw_input(text) + + def do_generate_acl(_): """ Regenerate the gitolite ACL file. @@ -288,7 +293,7 @@ def do_create_admin_token(args): print('%s. %s' % (idx, acl)) print('Which ACLs do you want to associated with this token?') - acls = raw_input('(Conna separated list): ') + acls = _get_input('(Coma separated list): ') acls_idx = [int(acl.strip()) for acl in acls.split(',')] acls = [acls_list[acl] for acl in acls_idx] From d4c9da2d9e55ff2e9a42fe0463333dd0e2fee0de Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Mar 22 2017 08:57:29 +0000 Subject: [PATCH 6/6] Add unit-tests for pagure-admin, especially the part for admin-token --- diff --git a/tests/test_pagure_admin.py b/tests/test_pagure_admin.py new file mode 100644 index 0000000..c21ea13 --- /dev/null +++ b/tests/test_pagure_admin.py @@ -0,0 +1,368 @@ +# -*- coding: utf-8 -*- + +""" + (c) 2017 - Copyright Red Hat Inc + + Authors: + Pierre-Yves Chibon + +""" + +__requires__ = ['SQLAlchemy >= 0.8'] +import pkg_resources # noqa + +import unittest # noqa +import shutil # noqa +import subprocess # noqa +import sys # noqa +import os # noqa + +import munch # noqa +from mock import patch, MagicMock # noqa + +sys.path.insert(0, os.path.join(os.path.dirname( + os.path.abspath(__file__)), '..')) + +import pagure.cli.admin # noqa +import pagure.lib.model # noqa +import tests # noqa + +PAGURE_ADMIN = os.path.abspath( + os.path.join(tests.HERE, '..', 'pagure', 'cli', 'admin.py')) + + +def _get_ouput(cmd): + """ Returns the std-out of the command specified. + + :arg cmd: the command to run provided as a list + :type cmd: list + + """ + my_env = os.environ.copy() + my_env["PYTHONPATH"] = os.path.abspath(os.path.join(tests.HERE, '..')) + output = subprocess.Popen( + cmd, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + env=my_env, + ).communicate() + + return output + + +class PagureAdminHelptests(tests.Modeltests): + """ Tests for pagure-admin --help """ + + def test_parse_arguments_help(self): + """ Test the parse_arguments function of pagure-admin. """ + cmd = ['python', PAGURE_ADMIN, '--help'] + self.assertEqual( + _get_ouput(cmd)[0], + '''usage: admin.py [-h] [--debug] + {refresh-gitolite,refresh-ssh,clear-hook-token,admin-token} + ... + +The admin CLI for this pagure instance + +optional arguments: + -h, --help show this help message and exit + --debug Increase the verbosity of the information displayed + +actions: + {refresh-gitolite,refresh-ssh,clear-hook-token,admin-token} + refresh-gitolite Re-generate the gitolite config file + refresh-ssh Re-write to disk every user's ssh key stored in the + database + clear-hook-token Generate a new hook token for every project in this + instance + admin-token Manages the admin tokens for this instance +''') + + def test_parser_refresh_gitolite_help(self): + """ Test the parser_refresh_gitolite function of pagure-admin. """ + cmd = ['python', PAGURE_ADMIN, 'refresh-gitolite', '--help'] + self.assertEqual( + _get_ouput(cmd)[0], + '''usage: admin.py refresh-gitolite [-h] + +optional arguments: + -h, --help show this help message and exit +''') + + def test_parser_refresh_ssh_help(self): + """ Test the parser_refresh_ssh function of pagure-admin. """ + cmd = ['python', PAGURE_ADMIN, 'refresh-ssh', '--help'] + self.assertEqual( + _get_ouput(cmd)[0], + '''usage: admin.py refresh-ssh [-h] + +optional arguments: + -h, --help show this help message and exit +''') + + def test_parser_clear_hook_token_help(self): + """ Test the parser_clear_hook_token function of pagure-admin. """ + cmd = ['python', PAGURE_ADMIN, 'clear-hook-token', '--help'] + self.assertEqual( + _get_ouput(cmd)[0], + '''usage: admin.py clear-hook-token [-h] + +optional arguments: + -h, --help show this help message and exit +''') + + def test_parser_admin_token_help(self): + """ Test the parser_admin_token function of pagure-admin. """ + cmd = ['python', PAGURE_ADMIN, 'admin-token', '--help'] + self.assertEqual( + _get_ouput(cmd)[0], + '''usage: admin.py admin-token [-h] {list,info,expire,create} ... + +optional arguments: + -h, --help show this help message and exit + +actions: + {list,info,expire,create} + list List the API admin token + info Provide some information about a specific API token + expire Expire a specific API token + create Create a new API token +''') + + def test_parser_admin_token_create_help(self): + """ Test the parser_admin_token_create function of pagure-admin. """ + cmd = ['python', PAGURE_ADMIN, 'admin-token', 'create', '--help'] + self.assertEqual( + _get_ouput(cmd)[0], + '''usage: admin.py admin-token create [-h] user + +positional arguments: + user User to associate with the token + +optional arguments: + -h, --help show this help message and exit +''') + + def test_parser_admin_token_list_help(self): + """ Test the _parser_admin_token_list function of pagure-admin. """ + cmd = ['python', PAGURE_ADMIN, 'admin-token', 'list', '--help'] + self.assertEqual( + _get_ouput(cmd)[0], + '''usage: admin.py admin-token list [-h] [--user USER] [--token TOKEN] [--active] + [--expired] + +optional arguments: + -h, --help show this help message and exit + --user USER User to associate or associated with the token + --token TOKEN API token + --active Only list active API token + --expired Only list expired API token +''') # noqa + + def test_parser_admin_token_info_help(self): + """ Test the _parser_admin_token_info function of pagure-admin. """ + cmd = ['python', PAGURE_ADMIN, 'admin-token', 'info', '--help'] + self.assertEqual( + _get_ouput(cmd)[0], + '''usage: admin.py admin-token info [-h] token + +positional arguments: + token API token + +optional arguments: + -h, --help show this help message and exit +''') + + def test_parser_admin_token_expire_help(self): + """ Test the _parser_admin_token_expire function of pagure-admin. """ + cmd = ['python', PAGURE_ADMIN, 'admin-token', 'expire', '--help'] + self.assertEqual( + _get_ouput(cmd)[0], + '''usage: admin.py admin-token expire [-h] token + +positional arguments: + token API token + +optional arguments: + -h, --help show this help message and exit +''') + + def test_parser_admin_token_invalid_help(self): + """ Test the _parser_admin_token_expire function of pagure-admin. """ + cmd = ['python', PAGURE_ADMIN, 'admin-token', 'foo', '--help'] + self.assertEqual( + _get_ouput(cmd)[1], + '''usage: admin.py admin-token [-h] {list,info,expire,create} ... +admin.py admin-token: error: invalid choice: 'foo' (choose from 'list', 'info', 'expire', 'create') +''') # noqa + + +class PagureAdminAdminTokenEmptytests(tests.Modeltests): + """ Tests for pagure-admin admin-token when there is nothing in the DB + """ + def setUp(self): + """ Set up the environnment, ran before every tests. """ + super(PagureAdminAdminTokenEmptytests, 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) + + def tearDown(self): + """ Tear down the environnment after running the tests. """ + super(PagureAdminAdminTokenEmptytests, self).tearDown() + del(os.environ['PAGURE_CONFIG']) + + def test_do_create_admin_token_no_user(self): + """ Test the do_create_admin_token function of pagure-admin without + user. + """ + cmd = ['python', PAGURE_ADMIN, 'admin-token', 'create', 'pingou'] + self.assertEqual(_get_ouput(cmd)[0], 'No user "pingou" found\n') + + def test_do_list_admin_token_empty(self): + """ Test the do_list_admin_token function of pagure-admin when there + are not tokens in the db. + """ + cmd = ['python', PAGURE_ADMIN, 'admin-token', 'list'] + self.assertEqual(_get_ouput(cmd)[0], 'No admin tokens found\n') + + +class PagureAdminAdminTokentests(tests.Modeltests): + """ Tests for pagure-admin admin-token """ + + def setUp(self): + """ Set up the environnment, ran before every tests. """ + super(PagureAdminAdminTokentests, 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) + 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(PagureAdminAdminTokentests, self).tearDown() + del(os.environ['PAGURE_CONFIG']) + + @patch('pagure.cli.admin._get_input') + @patch('pagure.cli.admin._ask_confirmation') + def test_do_create_admin_token(self, conf, rinp): + """ Test the do_create_admin_token function of pagure-admin. """ + conf.return_value = True + rinp.return_value = '1,2,3' + + args = munch.Munch({'user': 'pingou'}) + pagure.cli.admin.do_create_admin_token(args) + + # Check the outcome + cmd = ['python', PAGURE_ADMIN, 'admin-token', 'list'] + output = _get_ouput(cmd)[0] + self.assertNotEqual(output, 'No user "pingou" found\n') + self.assertEqual(len(output.split('\n')), 2) + self.assertIn(' -- pingou -- ', output) + + @patch('pagure.cli.admin._get_input') + @patch('pagure.cli.admin._ask_confirmation') + def test_do_info_admin_token(self, conf, rinp): + """ Test the do_info_admin_token function of pagure-admin. """ + # Create an admin token to use + conf.return_value = True + rinp.return_value = '1,2,3' + + args = munch.Munch({'user': 'pingou'}) + pagure.cli.admin.do_create_admin_token(args) + + # Retrieve the token + cmd = ['python', PAGURE_ADMIN, 'admin-token', 'list'] + output = _get_ouput(cmd)[0] + self.assertNotEqual(output, 'No user "pingou" found\n') + self.assertEqual(len(output.split('\n')), 2) + self.assertIn(' -- pingou -- ', output) + + token = output.split(' ', 1)[0] + + cmd = ['python', PAGURE_ADMIN, 'admin-token', 'info', token] + output = _get_ouput(cmd)[0] + self.assertIn(' -- pingou -- ', output.split('\n', 1)[0]) + self.assertEqual( + output.split('\n', 1)[1], '''ACLs: + - issue_create + - pull_request_comment + - pull_request_flag +''') + + @patch('pagure.cli.admin._get_input') + @patch('pagure.cli.admin._ask_confirmation') + def test_do_expire_admin_token(self, conf, rinp): + """ Test the do_expire_admin_token function of pagure-admin. """ + # Create an admin token to use + conf.return_value = True + rinp.return_value = '1,2,3' + + args = munch.Munch({'user': 'pingou'}) + pagure.cli.admin.do_create_admin_token(args) + + # Retrieve the token + cmd = ['python', PAGURE_ADMIN, 'admin-token', 'list'] + output = _get_ouput(cmd)[0] + self.assertNotEqual(output, 'No user "pingou" found\n') + self.assertEqual(len(output.split('\n')), 2) + self.assertIn(' -- pingou -- ', output) + + token = output.split(' ', 1)[0] + + # Before + cmd = ['python', PAGURE_ADMIN, 'admin-token', 'list', '--active'] + output = _get_ouput(cmd)[0] + self.assertNotEqual(output, 'No admin tokens found\n') + self.assertEqual(len(output.split('\n')), 2) + self.assertIn(' -- pingou -- ', output) + + # Expire the token + args = munch.Munch({'token': token}) + pagure.cli.admin.do_expire_admin_token(args) + + # After + cmd = ['python', PAGURE_ADMIN, 'admin-token', 'list', '--active'] + output = _get_ouput(cmd)[0] + self.assertEqual(output, 'No admin tokens found\n') + + +if __name__ == '__main__': + unittest.main(verbosity=2)