From 4cc8c017d960d325d4f36f707a5a3fb1bca8571e Mon Sep 17 00:00:00 2001 From: Clement Verna Date: Jan 11 2018 09:06:04 +0000 Subject: [PATCH 1/5] Add a new decorators module. This commit move the decorator that checks if a project has an issue tracker to a module dedicated to custom decorator. Signed-off-by: Clement Verna --- diff --git a/pagure/lib/decorators.py b/pagure/lib/decorators.py new file mode 100644 index 0000000..e992d33 --- /dev/null +++ b/pagure/lib/decorators.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- + +""" + (c) 2017 - Copyright Red Hat Inc + + Authors: + Clement Verna + +""" +import flask +from functools import wraps + + +def has_issue_tracker(function): + """ + Decorator that checks if the current pagure project has the + issue tracker active + If not active returns a 404 page + """ + @wraps(function) + def check_issue_tracker(*args, **kwargs): + repo = flask.g.repo + if not repo.settings.get('issue_tracker', True): + flask.abort(404, 'No issue tracker found for this project') + return function(*args, **kwargs) + + return check_issue_tracker diff --git a/pagure/ui/issues.py b/pagure/ui/issues.py index dd30ab7..9390436 100644 --- a/pagure/ui/issues.py +++ b/pagure/ui/issues.py @@ -19,7 +19,6 @@ import logging import os import re from collections import defaultdict -from functools import wraps from math import ceil import flask @@ -32,6 +31,7 @@ import pagure.doc_utils import pagure.exceptions import pagure.lib import pagure.lib.mimetype +from pagure.lib.decorators import has_issue_tracker import pagure.forms from pagure.config import config as pagure_config from pagure.ui import UI_NS @@ -46,22 +46,6 @@ from pagure.utils import ( _log = logging.getLogger(__name__) -def has_issue_tracker(function): - """ - Decorator that checks if the current pagure project has the - issue tracker active - If not active returns a 404 page - """ - @wraps(function) - def check_issue_tracker(*args, **kwargs): - repo = flask.g.repo - if not repo.settings.get('issue_tracker', True): - flask.abort(404, 'No issue tracker found for this project') - return function(*args, **kwargs) - - return check_issue_tracker - - @UI_NS.route( '//issue//update/', methods=['GET', 'POST']) @@ -1368,9 +1352,6 @@ def view_issue_raw_file( repo = flask.g.repo - if not repo.settings.get('issue_tracker', True): - flask.abort(404, 'No issue tracker found for this project') - attachdir = os.path.join( pagure_config['ATTACHMENTS_FOLDER'], repo.fullname) attachpath = os.path.join(attachdir, filename) From ea2e29266688eea89a9791e188e7fc894b4acfa5 Mon Sep 17 00:00:00 2001 From: Clement Verna Date: Jan 11 2018 09:06:04 +0000 Subject: [PATCH 2/5] Add decorator to check admin permission. This commit adds a new decorator that check if a user has admin permission to the project. Introduce the decorator in the ui/issues.py module. Signed-off-by: Clement Verna --- diff --git a/pagure/lib/decorators.py b/pagure/lib/decorators.py index e992d33..5878c27 100644 --- a/pagure/lib/decorators.py +++ b/pagure/lib/decorators.py @@ -25,3 +25,18 @@ def has_issue_tracker(function): return function(*args, **kwargs) return check_issue_tracker + + +def is_repo_admin(function): + """ + Decorator that checks if the current user is the admin of + the project. + If not active returns a 403 page + """ + @wraps(function) + def check_repo_admin(*args, **kwargs): + if not flask.g.repo_admin: + flask.abort(403, 'You are not allowed to change the \ + settings for this project') + return function(*args, **kwargs) + return check_repo_admin diff --git a/pagure/ui/issues.py b/pagure/ui/issues.py index 9390436..6fc6e32 100644 --- a/pagure/ui/issues.py +++ b/pagure/ui/issues.py @@ -31,7 +31,7 @@ import pagure.doc_utils import pagure.exceptions import pagure.lib import pagure.lib.mimetype -from pagure.lib.decorators import has_issue_tracker +from pagure.lib.decorators import has_issue_tracker, is_repo_admin import pagure.forms from pagure.config import config as pagure_config from pagure.ui import UI_NS @@ -379,17 +379,13 @@ def update_issue(repo, issueid, username=None, namespace=None): '/fork////tag//edit', methods=('GET', 'POST')) @login_required +@is_repo_admin @has_issue_tracker def edit_tag(repo, tag, username=None, namespace=None): """ Edit the specified tag associated with the issues of a project. """ repo = flask.g.repo - if not flask.g.repo_admin: - flask.abort( - 403, - 'You are not allowed to edit tags associated with the issues of \ - this project') tags = pagure.lib.get_tags_of_project(flask.g.session, repo) if not tags: @@ -449,6 +445,7 @@ def edit_tag(repo, tag, username=None, namespace=None): @UI_NS.route('//update/tags', methods=['POST']) @UI_NS.route('///update/tags', methods=['POST']) @login_required +@is_repo_admin @has_issue_tracker def update_tags(repo, username=None, namespace=None): """ Update the tags of a project. @@ -456,11 +453,6 @@ def update_tags(repo, username=None, namespace=None): repo = flask.g.repo - if not flask.g.repo_admin: - flask.abort( - 403, - 'You are not allowed to change the settings for this project') - form = pagure.forms.ConfirmationForm() error = False @@ -540,18 +532,13 @@ def update_tags(repo, username=None, namespace=None): @UI_NS.route('/fork///droptag/', methods=['POST']) @UI_NS.route('/fork////droptag/', methods=['POST']) @login_required +@is_repo_admin @has_issue_tracker def remove_tag(repo, username=None, namespace=None): """ Remove the specified tag, associated with the issues, from the project. """ repo = flask.g.repo - if not flask.g.repo_admin: - flask.abort( - 403, - 'You are not allowed to remove tags associated with the issues \ - of this project') - form = pagure.forms.DeleteIssueTagForm() if form.validate_on_submit(): tags = form.tag.data @@ -1499,13 +1486,10 @@ def edit_comment_issue( @UI_NS.route( '/fork////issues/reports', methods=['POST']) @login_required +@is_repo_admin def save_reports(repo, username=None, namespace=None): """ Marked for watching or Unwatching """ - if not flask.g.repo_admin: - flask.abort( - 403, - 'You are not allowed to create reports for this project') return_point = flask.url_for( 'ui_ns.view_issues', repo=repo, username=username, namespace=namespace) From bdb3e6dccb88e03c7ea57b781bafa869200f7624 Mon Sep 17 00:00:00 2001 From: Clement Verna Date: Jan 11 2018 09:06:04 +0000 Subject: [PATCH 3/5] Add is_repo_admin decorator to ui/plugins.py Signed-off-by: Clement Verna --- diff --git a/pagure/ui/plugins.py b/pagure/ui/plugins.py index 88ac26d..fc61ed1 100644 --- a/pagure/ui/plugins.py +++ b/pagure/ui/plugins.py @@ -23,6 +23,7 @@ import pagure.forms from pagure.exceptions import FileNotFoundException from pagure.ui import UI_NS from pagure.utils import login_required +from pagure.lib.decorators import is_repo_admin _log = logging.getLogger(__name__) @@ -69,16 +70,12 @@ _log = logging.getLogger(__name__) '/fork////settings//', methods=('GET', 'POST')) @login_required +@is_repo_admin def view_plugin(repo, plugin, username=None, namespace=None, full=True): """ Presents the settings of the project. """ repo = flask.g.repo - if not flask.g.repo_admin: - flask.abort( - 403, - 'You are not allowed to change the settings for this project') - # Private repos are not allowed to leak information outside so disabling CI # enables us to keep the repos totally discreate and prevents from leaking # information outside From 91fd114c26b44dcbfa4b773f088b92ee3ec9754e Mon Sep 17 00:00:00 2001 From: Clement Verna Date: Jan 11 2018 09:06:04 +0000 Subject: [PATCH 4/5] New decorator for admin session timeout. This commit adds a new decorator to check if an admin session has timedout. It introduce this decorator and the is_repo_admin to the ui/repo.py module Signed-off-by: Clement Verna --- diff --git a/pagure/lib/decorators.py b/pagure/lib/decorators.py index 5878c27..4ed0615 100644 --- a/pagure/lib/decorators.py +++ b/pagure/lib/decorators.py @@ -8,6 +8,7 @@ """ import flask +from pagure import admin_session_timedout from functools import wraps @@ -40,3 +41,19 @@ def is_repo_admin(function): settings for this project') return function(*args, **kwargs) return check_repo_admin + + +def is_admin_sess_timedout(function): + """ + Decorator that checks if the admin session has timeout. + If not true redirect to the login page + """ + @wraps(function) + def check_session_timeout(*args, **kwargs): + if admin_session_timedout(): + if flask.request.method == 'POST': + flask.flash('Action canceled, try it again', 'error') + return flask.redirect( + flask.url_for('auth_login', next=flask.request.url)) + return function(*args, **kwargs) + return check_session_timeout diff --git a/pagure/ui/repo.py b/pagure/ui/repo.py index 1912ea3..65be22c 100644 --- a/pagure/ui/repo.py +++ b/pagure/ui/repo.py @@ -49,7 +49,6 @@ import pagure.lib.tasks import pagure.forms import pagure.ui.plugins from pagure.config import config as pagure_config -from pagure.flask_app import admin_session_timedout from pagure.lib import encoding_utils from pagure.ui import UI_NS from pagure.utils import ( @@ -57,6 +56,7 @@ from pagure.utils import ( authenticated, login_required, ) +from pagure.lib.decorators import is_repo_admin, is_admin_sess_timedout _log = logging.getLogger(__name__) @@ -932,6 +932,7 @@ def view_tags(repo, username=None, namespace=None): @UI_NS.route( '/fork////upload', methods=('GET', 'POST')) @login_required +@is_repo_admin def new_release(repo, username=None, namespace=None): """ Upload a new release. """ @@ -941,11 +942,6 @@ def new_release(repo, username=None, namespace=None): repo = flask.g.repo - if not flask.g.repo_admin: - flask.abort( - 403, - 'You are not allowed to change the settings for this project') - form = pagure.forms.UploadFileForm() if form.validate_on_submit(): @@ -1002,23 +998,15 @@ def new_release(repo, username=None, namespace=None): @UI_NS.route( '/fork////settings', methods=('GET', 'POST')) @login_required +@is_admin_sess_timedout +@is_repo_admin def view_settings(repo, username=None, namespace=None): """ Presents the settings of the project. """ - if admin_session_timedout(): - if flask.request.method == 'POST': - flask.flash('Action canceled, try it again', 'error') - return flask.redirect( - flask.url_for('auth_login', next=flask.request.url)) repo = flask.g.repo repo_obj = flask.g.repo_obj - if not flask.g.repo_admin: - flask.abort( - 403, - 'You are not allowed to change the settings for this project') - plugins = pagure.lib.plugins.get_plugin_names( pagure_config.get('DISABLED_PLUGINS')) tags = pagure.lib.get_tags_of_project(flask.g.session, repo) @@ -1092,24 +1080,15 @@ def view_settings(repo, username=None, namespace=None): '/fork////settings/test_hook', methods=('GET', 'POST')) @login_required +@is_admin_sess_timedout +@is_repo_admin def test_web_hook(repo, username=None, namespace=None): """ Endpoint that can be called to send a test message to the web-hook service allowing to test the web-hooks set. """ - if admin_session_timedout(): - if flask.request.method == 'POST': - flask.flash('Action canceled, try it again', 'error') - return flask.redirect( - flask.url_for('auth_login', next=flask.request.url)) repo = flask.g.repo - if not flask.g.repo_admin: - flask.abort( - 403, - 'You are not allowed to trigger a test notification for this ' - 'project') - form = pagure.forms.ConfirmationForm() if form.validate_on_submit(): if pagure.lib.REDIS: @@ -1138,24 +1117,14 @@ def test_web_hook(repo, username=None, namespace=None): @UI_NS.route('/fork///update', methods=['POST']) @UI_NS.route('/fork////update', methods=['POST']) @login_required +@is_admin_sess_timedout +@is_repo_admin def update_project(repo, username=None, namespace=None): """ Update the description of a project. """ - if admin_session_timedout(): - flask.flash('Action canceled, try it again', 'error') - url = flask.url_for( - 'ui_ns.view_settings', username=username, repo=repo, - namespace=namespace) - return flask.redirect( - flask.url_for('auth_login', next=url)) repo = flask.g.repo - if not flask.g.repo_admin: - flask.abort( - 403, - 'You are not allowed to change the settings for this project') - form = pagure.forms.ProjectFormSimplified() if form.validate_on_submit(): @@ -1191,27 +1160,17 @@ def update_project(repo, username=None, namespace=None): '/fork////update/priorities', methods=['POST']) @login_required +@is_admin_sess_timedout +@is_repo_admin def update_priorities(repo, username=None, namespace=None): """ Update the priorities of a project. """ - if admin_session_timedout(): - flask.flash('Action canceled, try it again', 'error') - url = flask.url_for( - 'ui_ns.view_settings', username=username, repo=repo, - namespace=namespace) - return flask.redirect( - flask.url_for('auth_login', next=url)) repo = flask.g.repo if not repo.settings.get('issue_tracker', True): flask.abort(404, 'No issue tracker found for this project') - if not flask.g.repo_admin: - flask.abort( - 403, - 'You are not allowed to change the settings for this project') - form = pagure.forms.ConfirmationForm() error = False @@ -1293,27 +1252,17 @@ def update_priorities(repo, username=None, namespace=None): '/fork////update/default_priority', methods=['POST']) @login_required +@is_admin_sess_timedout +@is_repo_admin def default_priority(repo, username=None, namespace=None): """ Update the default priority of a project. """ - if admin_session_timedout(): - flask.flash('Action canceled, try it again', 'error') - url = flask.url_for( - 'ui_ns.view_settings', username=username, repo=repo, - namespace=namespace) - return flask.redirect( - flask.url_for('auth_login', next=url)) repo = flask.g.repo if not repo.settings.get('issue_tracker', True): flask.abort(404, 'No issue tracker found for this project') - if not flask.g.repo_admin: - flask.abort( - 403, - 'You are not allowed to change the settings for this project') - form = pagure.forms.DefaultPriorityForm( priorities=repo.priorities.values()) @@ -1344,27 +1293,17 @@ def default_priority(repo, username=None, namespace=None): '/fork////update/milestones', methods=['POST']) @login_required +@is_admin_sess_timedout +@is_repo_admin def update_milestones(repo, username=None, namespace=None): """ Update the milestones of a project. """ - if admin_session_timedout(): - flask.flash('Action canceled, try it again', 'error') - url = flask.url_for( - 'ui_ns.view_settings', username=username, repo=repo, - namespace=namespace) - return flask.redirect( - flask.url_for('auth_login', next=url)) repo = flask.g.repo if not repo.settings.get('issue_tracker', True): flask.abort(404, 'No issue tracker found for this project') - if not flask.g.repo_admin: - flask.abort( - 403, - 'You are not allowed to change the settings for this project') - form = pagure.forms.ConfirmationForm() error = False @@ -1436,26 +1375,15 @@ def update_milestones(repo, username=None, namespace=None): @UI_NS.route( '/fork////default/branch/', methods=['POST']) @login_required +@is_admin_sess_timedout +@is_repo_admin def change_ref_head(repo, username=None, namespace=None): """ Change HEAD reference """ - if admin_session_timedout(): - flask.flash('Action canceled, try it again', 'error') - url = flask.url_for( - 'ui_ns.view_settings', username=username, repo=repo, - namespace=namespace) - return flask.redirect( - flask.url_for('auth_login', next=url)) - repo = flask.g.repo repo_obj = flask.g.repo_obj - if not flask.g.repo_admin: - flask.abort( - 403, - 'You are not allowed to change the settings for this project') - branches = repo_obj.listall_branches() form = pagure.forms.DefaultBranchForm(branches=branches) @@ -1479,6 +1407,8 @@ def change_ref_head(repo, username=None, namespace=None): @UI_NS.route('/fork///delete', methods=['POST']) @UI_NS.route('/fork////delete', methods=['POST']) @login_required +@is_admin_sess_timedout +@is_repo_admin def delete_repo(repo, username=None, namespace=None): """ Delete the present project. """ @@ -1490,19 +1420,6 @@ def delete_repo(repo, username=None, namespace=None): or (repo.is_fork and not del_fork): flask.abort(404) - if admin_session_timedout(): - flask.flash('Action canceled, try it again', 'error') - url = flask.url_for( - 'ui_ns.view_settings', username=username, repo=repo, - namespace=namespace) - return flask.redirect( - flask.url_for('auth_login', next=url)) - - if not flask.g.repo_admin: - flask.abort( - 403, - 'You are not allowed to change the settings for this project') - if repo.read_only: flask.flash( 'The ACLs of this project are being refreshed in the backend ' @@ -1526,26 +1443,15 @@ def delete_repo(repo, username=None, namespace=None): @UI_NS.route( '/fork////hook_token', methods=['POST']) @login_required +@is_admin_sess_timedout +@is_repo_admin def new_repo_hook_token(repo, username=None, namespace=None): """ Re-generate a hook token for the present project. """ if not pagure_config.get('WEBHOOK', False): flask.abort(404) - if admin_session_timedout(): - flask.flash('Action canceled, try it again', 'error') - url = flask.url_for( - 'ui_ns.view_settings', username=username, repo=repo, - namespace=namespace) - return flask.redirect( - flask.url_for('auth_login', next=url)) - - repo = flask.g.repo - - if not flask.g.repo_admin: - flask.abort( - 403, - 'You are not allowed to change the settings for this project') + repo = flask.g.repo form = pagure.forms.ConfirmationForm() if not form.validate_on_submit(): @@ -1573,6 +1479,8 @@ def new_repo_hook_token(repo, username=None, namespace=None): '/fork////dropdeploykey/', methods=['POST']) @login_required +@is_admin_sess_timedout +@is_repo_admin def remove_deploykey(repo, keyid, username=None, namespace=None): """ Remove the specified deploy key from the project. """ @@ -1580,21 +1488,8 @@ def remove_deploykey(repo, keyid, username=None, namespace=None): if not pagure_config.get('DEPLOY_KEY', True): flask.abort(404, 'This pagure instance disabled deploy keys') - if admin_session_timedout(): - flask.flash('Action canceled, try it again', 'error') - url = flask.url_for( - 'ui_ns.view_settings', username=username, repo=repo, - namespace=namespace) - return flask.redirect( - flask.url_for('auth_login', next=url)) - repo = flask.g.repo - if not flask.g.repo_admin: - flask.abort( - 403, - 'You are not allowed to change the deploy keys for this project') - form = pagure.forms.ConfirmationForm() if form.validate_on_submit(): keyids = [str(key.id) for key in repo.deploykeys] @@ -1637,6 +1532,8 @@ def remove_deploykey(repo, keyid, username=None, namespace=None): '/fork////dropuser/', methods=['POST']) @login_required +@is_admin_sess_timedout +@is_repo_admin def remove_user(repo, userid, username=None, namespace=None): """ Remove the specified user from the project. """ @@ -1644,21 +1541,8 @@ def remove_user(repo, userid, username=None, namespace=None): if not pagure_config.get('ENABLE_USER_MNGT', True): flask.abort(404, 'User management not allowed in the pagure instance') - if admin_session_timedout(): - flask.flash('Action canceled, try it again', 'error') - url = flask.url_for( - 'ui_ns.view_settings', username=username, repo=repo, - namespace=namespace) - return flask.redirect( - flask.url_for('auth_login', next=url)) - repo = flask.g.repo - if not flask.g.repo_admin: - flask.abort( - 403, - 'You are not allowed to change the users for this project') - form = pagure.forms.ConfirmationForm() if form.validate_on_submit(): userids = [str(user.id) for user in repo.users] @@ -1714,6 +1598,8 @@ def remove_user(repo, userid, username=None, namespace=None): '/fork////adddeploykey', methods=('GET', 'POST')) @login_required +@is_admin_sess_timedout +@is_repo_admin def add_deploykey(repo, username=None, namespace=None): """ Add the specified deploy key to the project. """ @@ -1721,19 +1607,8 @@ def add_deploykey(repo, username=None, namespace=None): if not pagure_config.get('DEPLOY_KEY', True): flask.abort(404, 'This pagure instance disabled deploy keys') - if admin_session_timedout(): - if flask.request.method == 'POST': - flask.flash('Action canceled, try it again', 'error') - return flask.redirect( - flask.url_for('auth_login', next=flask.request.url)) - repo = flask.g.repo - if not flask.g.repo_admin: - flask.abort( - 403, - 'You are not allowed to add deploy keys to this project') - form = pagure.forms.AddDeployKeyForm() if form.validate_on_submit(): @@ -1781,6 +1656,8 @@ def add_deploykey(repo, username=None, namespace=None): @UI_NS.route( '/fork////adduser', methods=('GET', 'POST')) @login_required +@is_admin_sess_timedout +@is_repo_admin def add_user(repo, username=None, namespace=None): """ Add the specified user to the project. """ @@ -1789,19 +1666,8 @@ def add_user(repo, username=None, namespace=None): flask.abort( 404, 'User management is not allowed in this pagure instance') - if admin_session_timedout(): - if flask.request.method == 'POST': - flask.flash('Action canceled, try it again', 'error') - return flask.redirect( - flask.url_for('auth_login', next=flask.request.url)) - repo = flask.g.repo - if not flask.g.repo_admin: - flask.abort( - 403, - 'You are not allowed to add users to this project') - user_to_update = flask.request.args.get('user', '').strip() user_to_update_obj = None user_access = None @@ -1861,6 +1727,8 @@ def add_user(repo, username=None, namespace=None): '/fork////dropgroup/', methods=['POST']) @login_required +@is_admin_sess_timedout +@is_repo_admin def remove_group_project(repo, groupid, username=None, namespace=None): """ Remove the specified group from the project. """ @@ -1869,21 +1737,8 @@ def remove_group_project(repo, groupid, username=None, namespace=None): flask.abort( 404, 'User management is not allowed in this pagure instance') - if admin_session_timedout(): - flask.flash('Action canceled, try it again', 'error') - url = flask.url_for( - 'ui_ns.view_settings', username=username, repo=repo, - namespace=namespace) - return flask.redirect( - flask.url_for('auth_login', next=url)) - repo = flask.g.repo - if not flask.g.repo_admin: - flask.abort( - 403, - 'You are not allowed to change the users for this project') - form = pagure.forms.ConfirmationForm() if form.validate_on_submit(): grpids = [grp.id for grp in repo.groups] @@ -1927,6 +1782,8 @@ def remove_group_project(repo, groupid, username=None, namespace=None): @UI_NS.route( '/fork////addgroup', methods=('GET', 'POST')) @login_required +@is_admin_sess_timedout +@is_repo_admin def add_group_project(repo, username=None, namespace=None): """ Add the specified group to the project. """ @@ -1935,19 +1792,8 @@ def add_group_project(repo, username=None, namespace=None): flask.abort( 404, 'User management is not allowed in this pagure instance') - if admin_session_timedout(): - if flask.request.method == 'POST': - flask.flash('Action canceled, try it again', 'error') - return flask.redirect( - flask.url_for('auth_login', next=flask.request.url)) - repo = flask.g.repo - if not flask.g.repo_admin: - flask.abort( - 403, - 'You are not allowed to add groups to this project') - group_to_update = flask.request.args.get('group', '').strip() group_to_update_obj = None group_access = None @@ -2006,22 +1852,14 @@ def add_group_project(repo, username=None, namespace=None): @UI_NS.route( '/fork////regenerate', methods=['POST']) @login_required +@is_admin_sess_timedout +@is_repo_admin def regenerate_git(repo, username=None, namespace=None): """ Regenerate the specified git repo with the content in the project. """ - if admin_session_timedout(): - flask.flash('Action canceled, try it again', 'error') - url = flask.url_for( - 'ui_ns.view_settings', username=username, repo=repo, - namespace=namespace) - return flask.redirect( - flask.url_for('auth_login', next=url)) repo = flask.g.repo - if not flask.g.repo_admin: - flask.abort(403, 'You are not allowed to regenerate the git repos') - regenerate = flask.request.form.get('regenerate') if not regenerate or regenerate.lower() not in ['tickets', 'requests']: flask.abort(400, 'You can only regenerate tickest or requests repos') @@ -2079,14 +1917,10 @@ def regenerate_git(repo, username=None, namespace=None): '/fork////token/new', methods=('GET', 'POST')) @login_required +@is_admin_sess_timedout def add_token(repo, username=None, namespace=None): """ Add a token to a specified project. """ - if admin_session_timedout(): - if flask.request.method == 'POST': - flask.flash('Action canceled, try it again', 'error') - return flask.redirect( - flask.url_for('auth_login', next=flask.request.url)) repo = flask.g.repo @@ -2140,24 +1974,14 @@ def add_token(repo, username=None, namespace=None): '/fork////token/revoke/', methods=['POST']) @login_required +@is_admin_sess_timedout +@is_repo_admin def revoke_api_token(repo, token_id, username=None, namespace=None): """ Revokie a token to a specified project. """ - if admin_session_timedout(): - flask.flash('Action canceled, try it again', 'error') - url = flask.url_for( - 'ui_ns.view_settings', username=username, repo=repo, - namespace=namespace) - return flask.redirect( - flask.url_for('auth_login', next=url)) repo = flask.g.repo - if not flask.g.repo_admin: - flask.abort( - 403, - 'You are not allowed to change the settings for this project') - token = pagure.lib.get_api_token(flask.g.session, token_id) if not token \ @@ -2199,17 +2023,13 @@ def revoke_api_token(repo, token_id, username=None, namespace=None): '/fork////edit//f/' '', methods=('GET', 'POST')) @login_required +@is_repo_admin def edit_file(repo, branchname, filename, username=None, namespace=None): """ Edit a file online. """ repo = flask.g.repo repo_obj = flask.g.repo_obj - if not flask.g.repo_admin: - flask.abort( - 403, - 'You are not allowed to change the settings for this project') - user = pagure.lib.search_user( flask.g.session, username=flask.g.fas_user.username) @@ -2462,24 +2282,14 @@ def watch_repo(repo, watch, username=None, namespace=None): @UI_NS.route( '/fork////public_notif', methods=['POST']) @login_required +@is_admin_sess_timedout +@is_repo_admin def update_public_notifications(repo, username=None, namespace=None): """ Update the public notification settings of a project. """ - if admin_session_timedout(): - flask.flash('Action canceled, try it again', 'error') - url = flask.url_for( - 'ui_ns.view_settings', username=username, repo=repo, - namespace=namespace) - return flask.redirect( - flask.url_for('auth_login', next=url)) repo = flask.g.repo - if not flask.g.repo_admin: - flask.abort( - 403, - 'You are not allowed to change the settings for this project') - form = pagure.forms.PublicNotificationForm() if form.validate_on_submit(): @@ -2522,27 +2332,17 @@ def update_public_notifications(repo, username=None, namespace=None): '/fork////update/close_status', methods=['POST']) @login_required +@is_admin_sess_timedout +@is_repo_admin def update_close_status(repo, username=None, namespace=None): """ Update the close_status of a project. """ - if admin_session_timedout(): - flask.flash('Action canceled, try it again', 'error') - url = flask.url_for( - 'ui_ns.view_settings', username=username, repo=repo, - namespace=namespace) - return flask.redirect( - flask.url_for('auth_login', next=url)) repo = flask.g.repo if not repo.settings.get('issue_tracker', True): flask.abort(404, 'No issue tracker found for this project') - if not flask.g.repo_admin: - flask.abort( - 403, - 'You are not allowed to change the settings for this project') - form = pagure.forms.ConfirmationForm() if form.validate_on_submit(): @@ -2571,16 +2371,11 @@ def update_close_status(repo, username=None, namespace=None): '/fork////update/quick_replies', methods=['POST']) @login_required +@is_admin_sess_timedout +@is_repo_admin def update_quick_replies(repo, username=None, namespace=None): """ Update the quick_replies of a project. """ - if admin_session_timedout(): - flask.flash('Action canceled, try it again', 'error') - url = flask.url_for( - 'ui_ns.view_settings', username=username, repo=repo, - namespace=namespace) - return flask.redirect( - flask.url_for('auth_login', next=url)) repo = flask.g.repo @@ -2590,11 +2385,6 @@ def update_quick_replies(repo, username=None, namespace=None): 404, 'Issue tracker and pull requests are disabled for this project') - if not flask.g.repo_admin: - flask.abort( - 403, - 'You are not allowed to change the settings for this project') - form = pagure.forms.ConfirmationForm() if form.validate_on_submit(): @@ -2623,27 +2413,17 @@ def update_quick_replies(repo, username=None, namespace=None): '/fork////update/custom_keys', methods=['POST']) @login_required +@is_admin_sess_timedout +@is_repo_admin def update_custom_keys(repo, username=None, namespace=None): """ Update the custom_keys of a project. """ - if admin_session_timedout(): - flask.flash('Action canceled, try it again', 'error') - url = flask.url_for( - 'ui_ns.view_settings', username=username, repo=repo, - namespace=namespace) - return flask.redirect( - flask.url_for('auth_login', next=url)) repo = flask.g.repo if not repo.settings.get('issue_tracker', True): flask.abort(404, 'No issue tracker found for this project') - if not flask.g.repo_admin: - flask.abort( - 403, - 'You are not allowed to change the settings for this project') - form = pagure.forms.ConfirmationForm() if form.validate_on_submit(): @@ -2685,27 +2465,17 @@ def update_custom_keys(repo, username=None, namespace=None): '/fork////delete/report', methods=['POST']) @login_required +@is_admin_sess_timedout +@is_repo_admin def delete_report(repo, username=None, namespace=None): """ Delete a report from a project. """ - if admin_session_timedout(): - flask.flash('Action canceled, try it again', 'error') - url = flask.url_for( - 'ui_ns.view_settings', username=username, repo=repo, - namespace=namespace) - return flask.redirect( - flask.url_for('auth_login', next=url)) repo = flask.g.repo if not repo.settings.get('issue_tracker', True): flask.abort(404, 'No issue tracker found for this project') - if not flask.g.repo_admin: - flask.abort( - 403, - 'You are not allowed to change the settings for this project') - form = pagure.forms.ConfirmationForm() if form.validate_on_submit(): @@ -2736,27 +2506,16 @@ def delete_report(repo, username=None, namespace=None): '/fork////give', methods=['POST']) @login_required +@is_admin_sess_timedout +@is_repo_admin def give_project(repo, username=None, namespace=None): """ Give a project to someone else. """ if not pagure_config.get('ENABLE_GIVE_PROJECTS', True): flask.abort(404) - if admin_session_timedout(): - flask.flash('Action canceled, try it again', 'error') - url = flask.url_for( - 'ui_ns.view_settings', username=username, repo=repo, - namespace=namespace) - return flask.redirect( - flask.url_for('auth_login', next=url)) - repo = flask.g.repo - if not flask.g.repo_admin: - flask.abort( - 403, - 'You are not allowed to change the settings for this project') - if flask.g.fas_user.username != repo.user.user \ and not pagure.utils.is_admin(): flask.abort( diff --git a/tests/test_pagure_flask_ui_repo.py b/tests/test_pagure_flask_ui_repo.py index b6961ad..e5ae12e 100644 --- a/tests/test_pagure_flask_ui_repo.py +++ b/tests/test_pagure_flask_ui_repo.py @@ -45,7 +45,7 @@ class PagureFlaskRepotests(tests.Modeltests): pagure.config.config['UPLOAD_FOLDER_PATH'] = os.path.join( self.path, 'releases') - @patch('pagure.ui.repo.admin_session_timedout') + @patch('pagure.lib.decorators.admin_session_timedout') def test_add_user_when_user_mngt_off(self, ast): """ Test the add_user endpoint when user management is turned off in the pagure instance """ @@ -97,7 +97,7 @@ class PagureFlaskRepotests(tests.Modeltests): pagure.config.config['ENABLE_USER_MNGT'] = True - @patch('pagure.ui.repo.admin_session_timedout') + @patch('pagure.lib.decorators.admin_session_timedout') def test_add_deploykey(self, ast): """ Test the add_deploykey endpoint. """ ast.return_value = False @@ -199,7 +199,7 @@ class PagureFlaskRepotests(tests.Modeltests): self.assertIn('Deploy key added', output.data) self.assertIn('PUSH ACCESS', output.data) - @patch('pagure.ui.repo.admin_session_timedout') + @patch('pagure.lib.decorators.admin_session_timedout') @patch.dict('pagure.config.config', {'DEPLOY_KEY': False}) def test_add_deploykey_disabled(self, ast): """ Test the add_deploykey endpoint when it's disabled in the config. @@ -216,7 +216,7 @@ class PagureFlaskRepotests(tests.Modeltests): output = self.app.post('/test/adddeploykey') self.assertEqual(output.status_code, 404) - @patch('pagure.ui.repo.admin_session_timedout') + @patch('pagure.lib.decorators.admin_session_timedout') @patch('pagure.lib.notify.log') def test_add_user(self, mock_log, ast): """ Test the add_user endpoint. """ @@ -312,7 +312,7 @@ class PagureFlaskRepotests(tests.Modeltests): mock_log.assert_called_with(ANY, topic='project.user.added', msg=ANY, redis=ANY) - @patch('pagure.ui.repo.admin_session_timedout') + @patch('pagure.lib.decorators.admin_session_timedout') def test_add_group_project_when_user_mngt_off(self, ast): """ Test the add_group_project endpoint when user management is turned off in the pagure instance""" @@ -397,7 +397,7 @@ class PagureFlaskRepotests(tests.Modeltests): output.data) self.assertIn(u'No group ralph found.', output.data) - @patch('pagure.ui.repo.admin_session_timedout') + @patch('pagure.lib.decorators.admin_session_timedout') def test_add_group_project(self, ast): """ Test the add_group_project endpoint. """ ast.return_value = False @@ -488,7 +488,7 @@ class PagureFlaskRepotests(tests.Modeltests): self.assertIn( '\n Group added', output.data) - @patch('pagure.ui.repo.admin_session_timedout') + @patch('pagure.lib.decorators.admin_session_timedout') def test_remove_user_when_user_mngt_off(self, ast): """ Test the remove_user endpoint when user management is turned off in the pagure instance""" @@ -541,7 +541,7 @@ class PagureFlaskRepotests(tests.Modeltests): pagure.config.config['ENABLE_USER_MNGT'] = True - @patch('pagure.ui.repo.admin_session_timedout') + @patch('pagure.lib.decorators.admin_session_timedout') def test_remove_deploykey(self, ast): """ Test the remove_deploykey endpoint. """ ast.return_value = False @@ -616,7 +616,7 @@ class PagureFlaskRepotests(tests.Modeltests): self.assertIn('

Settings for test

', output.data) self.assertIn('Deploy key removed', output.data) - @patch('pagure.ui.repo.admin_session_timedout') + @patch('pagure.lib.decorators.admin_session_timedout') @patch.dict('pagure.config.config', {'DEPLOY_KEY': False}) def test_remove_deploykey_disabled(self, ast): """ Test the remove_deploykey endpoint when it's disabled in the @@ -631,7 +631,7 @@ class PagureFlaskRepotests(tests.Modeltests): output = self.app.post('/test/dropdeploykey/1') self.assertEqual(output.status_code, 404) - @patch('pagure.ui.repo.admin_session_timedout') + @patch('pagure.lib.decorators.admin_session_timedout') @patch('pagure.lib.notify.log') def test_remove_user(self, mock_log, ast): """ Test the remove_user endpoint. """ @@ -722,7 +722,7 @@ class PagureFlaskRepotests(tests.Modeltests): mock_log.assert_called_with(ANY, topic='project.user.removed', msg=ANY) - @patch('pagure.ui.repo.admin_session_timedout') + @patch('pagure.lib.decorators.admin_session_timedout') def test_remove_group_project_when_user_mngt_off(self, ast): """ Test the remove_group_project endpoint when user management is turned off in the pagure instance""" @@ -790,7 +790,7 @@ class PagureFlaskRepotests(tests.Modeltests): pagure.config.config['ENABLE_USER_MNGT'] = True - @patch('pagure.ui.repo.admin_session_timedout') + @patch('pagure.lib.decorators.admin_session_timedout') def test_remove_group_project(self, ast): """ Test the remove_group_project endpoint. """ ast.return_value = False @@ -896,7 +896,7 @@ class PagureFlaskRepotests(tests.Modeltests): repo = pagure.lib.get_authorized_project(self.session, 'test') self.assertEqual(len(repo.groups), 0) - @patch('pagure.ui.repo.admin_session_timedout') + @patch('pagure.lib.decorators.admin_session_timedout') def test_update_project(self, ast): """ Test the update_project endpoint. """ ast.return_value = True @@ -992,7 +992,7 @@ class PagureFlaskRepotests(tests.Modeltests): '\n Project updated', output.data) - @patch('pagure.ui.repo.admin_session_timedout') + @patch('pagure.lib.decorators.admin_session_timedout') def test_update_project_update_tag(self, ast): """ Test the view_settings endpoint when updating the project's tags. @@ -1069,7 +1069,7 @@ class PagureFlaskRepotests(tests.Modeltests): '\n Project updated', output.data) - @patch('pagure.ui.repo.admin_session_timedout') + @patch('pagure.lib.decorators.admin_session_timedout') def test_view_settings(self, ast): """ Test the view_settings endpoint. """ ast.return_value = False @@ -1195,7 +1195,7 @@ class PagureFlaskRepotests(tests.Modeltests): 'name="issue_tracker" checked=""/>', output.data) @patch('pagure.lib.git.generate_gitolite_acls') - @patch('pagure.ui.repo.admin_session_timedout') + @patch('pagure.lib.decorators.admin_session_timedout') def test_view_settings_pr_only(self, ast, gen_acl): """ Test the view_settings endpoint when turning on PR only. """ ast.return_value = False @@ -1254,7 +1254,7 @@ class PagureFlaskRepotests(tests.Modeltests): self.assertEqual(args[1].keys(), ['project']) self.assertEqual(args[1]['project'].fullname, 'test') - @patch('pagure.ui.repo.admin_session_timedout') + @patch('pagure.lib.decorators.admin_session_timedout') def test_fields_in_view_settings(self, ast): """ Test the default fields in view_settings endpoint. """ ast.return_value = False @@ -2757,7 +2757,7 @@ index 0000000..fb7093d @patch.dict('pagure.config.config', {'ENABLE_DEL_PROJECTS': False}) @patch('pagure.lib.notify.send_email') - @patch('pagure.ui.repo.admin_session_timedout') + @patch('pagure.lib.decorators.admin_session_timedout') def test_delete_repo_when_turned_off(self, ast, send_email): """ Test the delete_repo endpoint when deletion of a repo is turned off in the pagure instance """ @@ -2975,7 +2975,7 @@ index 0000000..fb7093d self.assertEqual(output.status_code, 404) @patch('pagure.lib.notify.send_email') - @patch('pagure.ui.repo.admin_session_timedout') + @patch('pagure.lib.decorators.admin_session_timedout') def test_delete_read_only_repo(self, ast, send_email): """ Test the delete_repo endpoint when the repo is read_only """ ast.return_value = False @@ -3025,7 +3025,7 @@ index 0000000..fb7093d output.data) @patch('pagure.lib.notify.send_email', MagicMock(return_value=True)) - @patch('pagure.ui.repo.admin_session_timedout') + @patch('pagure.lib.decorators.admin_session_timedout') def test_delete_repo(self, ast): """ Test the delete_repo endpoint. """ ast.return_value = False @@ -3294,7 +3294,7 @@ index 0000000..fb7093d @patch.dict('pagure.config.config', {'TICKETS_FOLDER': None}) @patch('pagure.lib.notify.send_email', MagicMock(return_value=True)) - @patch('pagure.ui.repo.admin_session_timedout', MagicMock(return_value=False)) + @patch('pagure.lib.decorators.admin_session_timedout', MagicMock(return_value=False)) def test_delete_repo_no_ticket(self): """ Test the delete_repo endpoint when tickets aren't enabled in this pagure instance. """ @@ -3333,7 +3333,7 @@ index 0000000..fb7093d output.data) @patch('pagure.lib.notify.send_email') - @patch('pagure.ui.repo.admin_session_timedout') + @patch('pagure.lib.decorators.admin_session_timedout') def test_delete_repo_with_users(self, ast, send_email): """ Test the delete_repo endpoint. """ ast.return_value = False @@ -3421,7 +3421,7 @@ index 0000000..fb7093d self.assertEqual(repo, None) @patch('pagure.lib.notify.send_email') - @patch('pagure.ui.repo.admin_session_timedout') + @patch('pagure.lib.decorators.admin_session_timedout') def test_delete_repo_with_group(self, ast, send_email): """ Test the delete_repo endpoint. """ ast.return_value = False @@ -3523,7 +3523,7 @@ index 0000000..fb7093d self.assertEqual(repo, None) @patch('pagure.lib.notify.send_email') - @patch('pagure.ui.repo.admin_session_timedout') + @patch('pagure.lib.decorators.admin_session_timedout') def test_delete_repo_with_coloredtag(self, ast, send_email): """ Test the delete_repo endpoint. """ ast.return_value = False @@ -3617,7 +3617,7 @@ index 0000000..fb7093d repo = pagure.lib.get_authorized_project(self.session, 'test2') self.assertEqual(repo, None) - @patch('pagure.ui.repo.admin_session_timedout') + @patch('pagure.lib.decorators.admin_session_timedout') def test_new_repo_hook_token(self, ast): """ Test the new_repo_hook_token endpoint. """ ast.return_value = False @@ -3677,7 +3677,7 @@ index 0000000..fb7093d self.assertNotEqual(repo.hook_token, 'aaabbbccc') @patch('pagure.lib.notify.send_email') - @patch('pagure.ui.repo.admin_session_timedout') + @patch('pagure.lib.decorators.admin_session_timedout') @patch('pagure.lib.git.update_git') def test_regenerate_git(self, upgit, ast, sendmail): """ Test the regenerate_git endpoint. """ @@ -3987,7 +3987,7 @@ index 0000000..fb7093d self.assertIn( '

No content found

', output.data) - @patch('pagure.ui.repo.admin_session_timedout') + @patch('pagure.lib.decorators.admin_session_timedout') def test_change_ref_head(self,ast): """ Test the change_ref_head endpoint. """ ast.return_value = True @@ -4187,7 +4187,7 @@ index 0000000..fb7093d 'been uploaded', output.data) self.assertIn('This project has not been tagged.', output.data) - @patch('pagure.ui.repo.admin_session_timedout') + @patch('pagure.lib.decorators.admin_session_timedout') def test_add_token_all_tokens(self, ast): """ Test the add_token endpoint. """ ast.return_value = False @@ -4206,7 +4206,7 @@ index 0000000..fb7093d ) @patch.dict('pagure.config.config', {'USER_ACLS': ['create_project']}) - @patch('pagure.ui.repo.admin_session_timedout') + @patch('pagure.lib.decorators.admin_session_timedout') def test_add_token_one_token(self, ast): """ Test the add_token endpoint. """ ast.return_value = False @@ -4224,7 +4224,7 @@ index 0000000..fb7093d 1 ) - @patch('pagure.ui.repo.admin_session_timedout') + @patch('pagure.lib.decorators.admin_session_timedout') def test_add_token(self, ast): """ Test the add_token endpoint. """ ast.return_value = False @@ -4298,7 +4298,7 @@ index 0000000..fb7093d 'Valid until: ', output.data) - @patch('pagure.ui.repo.admin_session_timedout') + @patch('pagure.lib.decorators.admin_session_timedout') def test_revoke_api_token(self, ast): """ Test the revoke_api_token endpoint. """ ast.return_value = False From afe47547c8e0b3b5e9bafeffeb431175b30e345b Mon Sep 17 00:00:00 2001 From: Clement Verna Date: Jan 11 2018 09:06:04 +0000 Subject: [PATCH 5/5] Use issue tracker decorator in ui/repo.py This commit adds the decorators to ui/repo.py and also move out the decorator module out of the lib folder. --- diff --git a/pagure/decorators.py b/pagure/decorators.py new file mode 100644 index 0000000..dac2c8a --- /dev/null +++ b/pagure/decorators.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- + +""" + (c) 2018 - Copyright Red Hat Inc + + Authors: + Clement Verna + +""" +import flask +from pagure.flask_app import admin_session_timedout +from functools import wraps + + +def has_issue_tracker(function): + """ + Decorator that checks if the current pagure project has the + issue tracker active + If not active returns a 404 page + """ + @wraps(function) + def check_issue_tracker(*args, **kwargs): + repo = flask.g.repo + if not repo.settings.get('issue_tracker', True): + flask.abort(404, 'No issue tracker found for this project') + return function(*args, **kwargs) + + return check_issue_tracker + + +def is_repo_admin(function): + """ + Decorator that checks if the current user is the admin of + the project. + If not active returns a 403 page + """ + @wraps(function) + def check_repo_admin(*args, **kwargs): + if not flask.g.repo_admin: + flask.abort(403, 'You are not allowed to change the ' + 'settings for this project') + return function(*args, **kwargs) + return check_repo_admin + + +def is_admin_sess_timedout(function): + """ + Decorator that checks if the admin session has timeout. + If not true redirect to the login page + """ + @wraps(function) + def check_session_timeout(*args, **kwargs): + if admin_session_timedout(): + if flask.request.method == 'POST': + flask.flash('Action canceled, try it again', 'error') + return flask.redirect( + flask.url_for('auth_login', next=flask.request.url)) + return function(*args, **kwargs) + return check_session_timeout diff --git a/pagure/lib/decorators.py b/pagure/lib/decorators.py deleted file mode 100644 index 4ed0615..0000000 --- a/pagure/lib/decorators.py +++ /dev/null @@ -1,59 +0,0 @@ -# -*- coding: utf-8 -*- - -""" - (c) 2017 - Copyright Red Hat Inc - - Authors: - Clement Verna - -""" -import flask -from pagure import admin_session_timedout -from functools import wraps - - -def has_issue_tracker(function): - """ - Decorator that checks if the current pagure project has the - issue tracker active - If not active returns a 404 page - """ - @wraps(function) - def check_issue_tracker(*args, **kwargs): - repo = flask.g.repo - if not repo.settings.get('issue_tracker', True): - flask.abort(404, 'No issue tracker found for this project') - return function(*args, **kwargs) - - return check_issue_tracker - - -def is_repo_admin(function): - """ - Decorator that checks if the current user is the admin of - the project. - If not active returns a 403 page - """ - @wraps(function) - def check_repo_admin(*args, **kwargs): - if not flask.g.repo_admin: - flask.abort(403, 'You are not allowed to change the \ - settings for this project') - return function(*args, **kwargs) - return check_repo_admin - - -def is_admin_sess_timedout(function): - """ - Decorator that checks if the admin session has timeout. - If not true redirect to the login page - """ - @wraps(function) - def check_session_timeout(*args, **kwargs): - if admin_session_timedout(): - if flask.request.method == 'POST': - flask.flash('Action canceled, try it again', 'error') - return flask.redirect( - flask.url_for('auth_login', next=flask.request.url)) - return function(*args, **kwargs) - return check_session_timeout diff --git a/pagure/ui/issues.py b/pagure/ui/issues.py index 6fc6e32..c53f87d 100644 --- a/pagure/ui/issues.py +++ b/pagure/ui/issues.py @@ -31,7 +31,7 @@ import pagure.doc_utils import pagure.exceptions import pagure.lib import pagure.lib.mimetype -from pagure.lib.decorators import has_issue_tracker, is_repo_admin +from pagure.decorators import has_issue_tracker, is_repo_admin import pagure.forms from pagure.config import config as pagure_config from pagure.ui import UI_NS @@ -386,7 +386,6 @@ def edit_tag(repo, tag, username=None, namespace=None): """ repo = flask.g.repo - tags = pagure.lib.get_tags_of_project(flask.g.session, repo) if not tags: flask.abort(404, 'Project has no tags to edit') diff --git a/pagure/ui/plugins.py b/pagure/ui/plugins.py index fc61ed1..bc0207a 100644 --- a/pagure/ui/plugins.py +++ b/pagure/ui/plugins.py @@ -23,7 +23,7 @@ import pagure.forms from pagure.exceptions import FileNotFoundException from pagure.ui import UI_NS from pagure.utils import login_required -from pagure.lib.decorators import is_repo_admin +from pagure.decorators import is_repo_admin _log = logging.getLogger(__name__) diff --git a/pagure/ui/repo.py b/pagure/ui/repo.py index 65be22c..625eec0 100644 --- a/pagure/ui/repo.py +++ b/pagure/ui/repo.py @@ -56,8 +56,10 @@ from pagure.utils import ( authenticated, login_required, ) -from pagure.lib.decorators import is_repo_admin, is_admin_sess_timedout - +from pagure.decorators import ( + is_repo_admin, + is_admin_sess_timedout, + has_issue_tracker) _log = logging.getLogger(__name__) @@ -1160,6 +1162,7 @@ def update_project(repo, username=None, namespace=None): '/fork////update/priorities', methods=['POST']) @login_required +@has_issue_tracker @is_admin_sess_timedout @is_repo_admin def update_priorities(repo, username=None, namespace=None): @@ -1168,9 +1171,6 @@ def update_priorities(repo, username=None, namespace=None): repo = flask.g.repo - if not repo.settings.get('issue_tracker', True): - flask.abort(404, 'No issue tracker found for this project') - form = pagure.forms.ConfirmationForm() error = False @@ -1252,6 +1252,7 @@ def update_priorities(repo, username=None, namespace=None): '/fork////update/default_priority', methods=['POST']) @login_required +@has_issue_tracker @is_admin_sess_timedout @is_repo_admin def default_priority(repo, username=None, namespace=None): @@ -1260,9 +1261,6 @@ def default_priority(repo, username=None, namespace=None): repo = flask.g.repo - if not repo.settings.get('issue_tracker', True): - flask.abort(404, 'No issue tracker found for this project') - form = pagure.forms.DefaultPriorityForm( priorities=repo.priorities.values()) @@ -1293,6 +1291,7 @@ def default_priority(repo, username=None, namespace=None): '/fork////update/milestones', methods=['POST']) @login_required +@has_issue_tracker @is_admin_sess_timedout @is_repo_admin def update_milestones(repo, username=None, namespace=None): @@ -1301,9 +1300,6 @@ def update_milestones(repo, username=None, namespace=None): repo = flask.g.repo - if not repo.settings.get('issue_tracker', True): - flask.abort(404, 'No issue tracker found for this project') - form = pagure.forms.ConfirmationForm() error = False @@ -1451,7 +1447,7 @@ def new_repo_hook_token(repo, username=None, namespace=None): if not pagure_config.get('WEBHOOK', False): flask.abort(404) - repo = flask.g.repo + repo = flask.g.repo form = pagure.forms.ConfirmationForm() if not form.validate_on_submit(): @@ -2332,6 +2328,7 @@ def update_public_notifications(repo, username=None, namespace=None): '/fork////update/close_status', methods=['POST']) @login_required +@has_issue_tracker @is_admin_sess_timedout @is_repo_admin def update_close_status(repo, username=None, namespace=None): @@ -2340,9 +2337,6 @@ def update_close_status(repo, username=None, namespace=None): repo = flask.g.repo - if not repo.settings.get('issue_tracker', True): - flask.abort(404, 'No issue tracker found for this project') - form = pagure.forms.ConfirmationForm() if form.validate_on_submit(): @@ -2371,6 +2365,7 @@ def update_close_status(repo, username=None, namespace=None): '/fork////update/quick_replies', methods=['POST']) @login_required +@has_issue_tracker @is_admin_sess_timedout @is_repo_admin def update_quick_replies(repo, username=None, namespace=None): @@ -2379,11 +2374,8 @@ def update_quick_replies(repo, username=None, namespace=None): repo = flask.g.repo - if (not repo.settings.get('issue_tracker', True) and - not repo.settings.get('pull_requests', True)): - flask.abort( - 404, - 'Issue tracker and pull requests are disabled for this project') + if (not repo.settings.get('pull_requests', True)): + flask.abort(404, 'Pull requests are disabled for this project') form = pagure.forms.ConfirmationForm() @@ -2413,6 +2405,7 @@ def update_quick_replies(repo, username=None, namespace=None): '/fork////update/custom_keys', methods=['POST']) @login_required +@has_issue_tracker @is_admin_sess_timedout @is_repo_admin def update_custom_keys(repo, username=None, namespace=None): @@ -2421,9 +2414,6 @@ def update_custom_keys(repo, username=None, namespace=None): repo = flask.g.repo - if not repo.settings.get('issue_tracker', True): - flask.abort(404, 'No issue tracker found for this project') - form = pagure.forms.ConfirmationForm() if form.validate_on_submit(): @@ -2465,6 +2455,7 @@ def update_custom_keys(repo, username=None, namespace=None): '/fork////delete/report', methods=['POST']) @login_required +@has_issue_tracker @is_admin_sess_timedout @is_repo_admin def delete_report(repo, username=None, namespace=None): @@ -2473,9 +2464,6 @@ def delete_report(repo, username=None, namespace=None): repo = flask.g.repo - if not repo.settings.get('issue_tracker', True): - flask.abort(404, 'No issue tracker found for this project') - form = pagure.forms.ConfirmationForm() if form.validate_on_submit(): diff --git a/tests/test_pagure_flask_api_ui_private_repo.py b/tests/test_pagure_flask_api_ui_private_repo.py index 339214c..af0c242 100644 --- a/tests/test_pagure_flask_api_ui_private_repo.py +++ b/tests/test_pagure_flask_api_ui_private_repo.py @@ -537,7 +537,7 @@ class PagurePrivateRepotest(tests.Modeltests): self.assertEqual( output.get_data(as_text=True).count('
'), 6) - @patch('pagure.ui.repo.admin_session_timedout') + @patch('pagure.decorators.admin_session_timedout') def test_private_settings_ui(self, ast): """ Test UI for private repo""" ast.return_value = False @@ -588,7 +588,7 @@ class PagurePrivateRepotest(tests.Modeltests): '', output.get_data(as_text=True)) - @patch('pagure.ui.repo.admin_session_timedout') + @patch('pagure.decorators.admin_session_timedout') def test_private_settings_ui_update_privacy_false(self, ast): """ Test UI for private repo""" ast.return_value = False @@ -644,7 +644,7 @@ class PagurePrivateRepotest(tests.Modeltests): repo = pagure.lib._get_project(self.session, 'test4') self.assertFalse(repo.private) - @patch('pagure.ui.repo.admin_session_timedout') + @patch('pagure.decorators.admin_session_timedout') def test_private_settings_ui_update_privacy_true(self, ast): """ Test UI for private repo""" ast.return_value = False diff --git a/tests/test_pagure_flask_ui_repo.py b/tests/test_pagure_flask_ui_repo.py index e5ae12e..f53aaa9 100644 --- a/tests/test_pagure_flask_ui_repo.py +++ b/tests/test_pagure_flask_ui_repo.py @@ -45,7 +45,7 @@ class PagureFlaskRepotests(tests.Modeltests): pagure.config.config['UPLOAD_FOLDER_PATH'] = os.path.join( self.path, 'releases') - @patch('pagure.lib.decorators.admin_session_timedout') + @patch('pagure.decorators.admin_session_timedout') def test_add_user_when_user_mngt_off(self, ast): """ Test the add_user endpoint when user management is turned off in the pagure instance """ @@ -97,7 +97,7 @@ class PagureFlaskRepotests(tests.Modeltests): pagure.config.config['ENABLE_USER_MNGT'] = True - @patch('pagure.lib.decorators.admin_session_timedout') + @patch('pagure.decorators.admin_session_timedout') def test_add_deploykey(self, ast): """ Test the add_deploykey endpoint. """ ast.return_value = False @@ -199,7 +199,7 @@ class PagureFlaskRepotests(tests.Modeltests): self.assertIn('Deploy key added', output.data) self.assertIn('PUSH ACCESS', output.data) - @patch('pagure.lib.decorators.admin_session_timedout') + @patch('pagure.decorators.admin_session_timedout') @patch.dict('pagure.config.config', {'DEPLOY_KEY': False}) def test_add_deploykey_disabled(self, ast): """ Test the add_deploykey endpoint when it's disabled in the config. @@ -216,7 +216,7 @@ class PagureFlaskRepotests(tests.Modeltests): output = self.app.post('/test/adddeploykey') self.assertEqual(output.status_code, 404) - @patch('pagure.lib.decorators.admin_session_timedout') + @patch('pagure.decorators.admin_session_timedout') @patch('pagure.lib.notify.log') def test_add_user(self, mock_log, ast): """ Test the add_user endpoint. """ @@ -312,7 +312,7 @@ class PagureFlaskRepotests(tests.Modeltests): mock_log.assert_called_with(ANY, topic='project.user.added', msg=ANY, redis=ANY) - @patch('pagure.lib.decorators.admin_session_timedout') + @patch('pagure.decorators.admin_session_timedout') def test_add_group_project_when_user_mngt_off(self, ast): """ Test the add_group_project endpoint when user management is turned off in the pagure instance""" @@ -372,7 +372,7 @@ class PagureFlaskRepotests(tests.Modeltests): pagure.config.config['ENABLE_USER_MNGT'] = True @patch.dict('pagure.config.config', {'ENABLE_GROUP_MNGT': False}) - @patch('pagure.ui.repo.admin_session_timedout') + @patch('pagure.decorators.admin_session_timedout') def test_add_group_project_grp_mngt_off(self, ast): """ Test the add_group_project endpoint when group management is turned off in the pagure instance""" @@ -397,7 +397,7 @@ class PagureFlaskRepotests(tests.Modeltests): output.data) self.assertIn(u'No group ralph found.', output.data) - @patch('pagure.lib.decorators.admin_session_timedout') + @patch('pagure.decorators.admin_session_timedout') def test_add_group_project(self, ast): """ Test the add_group_project endpoint. """ ast.return_value = False @@ -488,7 +488,7 @@ class PagureFlaskRepotests(tests.Modeltests): self.assertIn( '\n Group added', output.data) - @patch('pagure.lib.decorators.admin_session_timedout') + @patch('pagure.decorators.admin_session_timedout') def test_remove_user_when_user_mngt_off(self, ast): """ Test the remove_user endpoint when user management is turned off in the pagure instance""" @@ -541,7 +541,7 @@ class PagureFlaskRepotests(tests.Modeltests): pagure.config.config['ENABLE_USER_MNGT'] = True - @patch('pagure.lib.decorators.admin_session_timedout') + @patch('pagure.decorators.admin_session_timedout') def test_remove_deploykey(self, ast): """ Test the remove_deploykey endpoint. """ ast.return_value = False @@ -616,7 +616,7 @@ class PagureFlaskRepotests(tests.Modeltests): self.assertIn('

Settings for test

', output.data) self.assertIn('Deploy key removed', output.data) - @patch('pagure.lib.decorators.admin_session_timedout') + @patch('pagure.decorators.admin_session_timedout') @patch.dict('pagure.config.config', {'DEPLOY_KEY': False}) def test_remove_deploykey_disabled(self, ast): """ Test the remove_deploykey endpoint when it's disabled in the @@ -631,7 +631,7 @@ class PagureFlaskRepotests(tests.Modeltests): output = self.app.post('/test/dropdeploykey/1') self.assertEqual(output.status_code, 404) - @patch('pagure.lib.decorators.admin_session_timedout') + @patch('pagure.decorators.admin_session_timedout') @patch('pagure.lib.notify.log') def test_remove_user(self, mock_log, ast): """ Test the remove_user endpoint. """ @@ -722,7 +722,7 @@ class PagureFlaskRepotests(tests.Modeltests): mock_log.assert_called_with(ANY, topic='project.user.removed', msg=ANY) - @patch('pagure.lib.decorators.admin_session_timedout') + @patch('pagure.decorators.admin_session_timedout') def test_remove_group_project_when_user_mngt_off(self, ast): """ Test the remove_group_project endpoint when user management is turned off in the pagure instance""" @@ -790,7 +790,7 @@ class PagureFlaskRepotests(tests.Modeltests): pagure.config.config['ENABLE_USER_MNGT'] = True - @patch('pagure.lib.decorators.admin_session_timedout') + @patch('pagure.decorators.admin_session_timedout') def test_remove_group_project(self, ast): """ Test the remove_group_project endpoint. """ ast.return_value = False @@ -896,7 +896,7 @@ class PagureFlaskRepotests(tests.Modeltests): repo = pagure.lib.get_authorized_project(self.session, 'test') self.assertEqual(len(repo.groups), 0) - @patch('pagure.lib.decorators.admin_session_timedout') + @patch('pagure.decorators.admin_session_timedout') def test_update_project(self, ast): """ Test the update_project endpoint. """ ast.return_value = True @@ -992,7 +992,7 @@ class PagureFlaskRepotests(tests.Modeltests): '\n Project updated', output.data) - @patch('pagure.lib.decorators.admin_session_timedout') + @patch('pagure.decorators.admin_session_timedout') def test_update_project_update_tag(self, ast): """ Test the view_settings endpoint when updating the project's tags. @@ -1069,7 +1069,7 @@ class PagureFlaskRepotests(tests.Modeltests): '\n Project updated', output.data) - @patch('pagure.lib.decorators.admin_session_timedout') + @patch('pagure.decorators.admin_session_timedout') def test_view_settings(self, ast): """ Test the view_settings endpoint. """ ast.return_value = False @@ -1195,7 +1195,7 @@ class PagureFlaskRepotests(tests.Modeltests): 'name="issue_tracker" checked=""/>', output.data) @patch('pagure.lib.git.generate_gitolite_acls') - @patch('pagure.lib.decorators.admin_session_timedout') + @patch('pagure.decorators.admin_session_timedout') def test_view_settings_pr_only(self, ast, gen_acl): """ Test the view_settings endpoint when turning on PR only. """ ast.return_value = False @@ -1254,7 +1254,7 @@ class PagureFlaskRepotests(tests.Modeltests): self.assertEqual(args[1].keys(), ['project']) self.assertEqual(args[1]['project'].fullname, 'test') - @patch('pagure.lib.decorators.admin_session_timedout') + @patch('pagure.decorators.admin_session_timedout') def test_fields_in_view_settings(self, ast): """ Test the default fields in view_settings endpoint. """ ast.return_value = False @@ -2757,7 +2757,7 @@ index 0000000..fb7093d @patch.dict('pagure.config.config', {'ENABLE_DEL_PROJECTS': False}) @patch('pagure.lib.notify.send_email') - @patch('pagure.lib.decorators.admin_session_timedout') + @patch('pagure.decorators.admin_session_timedout') def test_delete_repo_when_turned_off(self, ast, send_email): """ Test the delete_repo endpoint when deletion of a repo is turned off in the pagure instance """ @@ -2975,7 +2975,7 @@ index 0000000..fb7093d self.assertEqual(output.status_code, 404) @patch('pagure.lib.notify.send_email') - @patch('pagure.lib.decorators.admin_session_timedout') + @patch('pagure.decorators.admin_session_timedout') def test_delete_read_only_repo(self, ast, send_email): """ Test the delete_repo endpoint when the repo is read_only """ ast.return_value = False @@ -3025,7 +3025,7 @@ index 0000000..fb7093d output.data) @patch('pagure.lib.notify.send_email', MagicMock(return_value=True)) - @patch('pagure.lib.decorators.admin_session_timedout') + @patch('pagure.decorators.admin_session_timedout') def test_delete_repo(self, ast): """ Test the delete_repo endpoint. """ ast.return_value = False @@ -3294,7 +3294,7 @@ index 0000000..fb7093d @patch.dict('pagure.config.config', {'TICKETS_FOLDER': None}) @patch('pagure.lib.notify.send_email', MagicMock(return_value=True)) - @patch('pagure.lib.decorators.admin_session_timedout', MagicMock(return_value=False)) + @patch('pagure.decorators.admin_session_timedout', MagicMock(return_value=False)) def test_delete_repo_no_ticket(self): """ Test the delete_repo endpoint when tickets aren't enabled in this pagure instance. """ @@ -3333,7 +3333,7 @@ index 0000000..fb7093d output.data) @patch('pagure.lib.notify.send_email') - @patch('pagure.lib.decorators.admin_session_timedout') + @patch('pagure.decorators.admin_session_timedout') def test_delete_repo_with_users(self, ast, send_email): """ Test the delete_repo endpoint. """ ast.return_value = False @@ -3421,7 +3421,7 @@ index 0000000..fb7093d self.assertEqual(repo, None) @patch('pagure.lib.notify.send_email') - @patch('pagure.lib.decorators.admin_session_timedout') + @patch('pagure.decorators.admin_session_timedout') def test_delete_repo_with_group(self, ast, send_email): """ Test the delete_repo endpoint. """ ast.return_value = False @@ -3523,7 +3523,7 @@ index 0000000..fb7093d self.assertEqual(repo, None) @patch('pagure.lib.notify.send_email') - @patch('pagure.lib.decorators.admin_session_timedout') + @patch('pagure.decorators.admin_session_timedout') def test_delete_repo_with_coloredtag(self, ast, send_email): """ Test the delete_repo endpoint. """ ast.return_value = False @@ -3617,7 +3617,7 @@ index 0000000..fb7093d repo = pagure.lib.get_authorized_project(self.session, 'test2') self.assertEqual(repo, None) - @patch('pagure.lib.decorators.admin_session_timedout') + @patch('pagure.decorators.admin_session_timedout') def test_new_repo_hook_token(self, ast): """ Test the new_repo_hook_token endpoint. """ ast.return_value = False @@ -3677,7 +3677,7 @@ index 0000000..fb7093d self.assertNotEqual(repo.hook_token, 'aaabbbccc') @patch('pagure.lib.notify.send_email') - @patch('pagure.lib.decorators.admin_session_timedout') + @patch('pagure.decorators.admin_session_timedout') @patch('pagure.lib.git.update_git') def test_regenerate_git(self, upgit, ast, sendmail): """ Test the regenerate_git endpoint. """ @@ -3987,7 +3987,7 @@ index 0000000..fb7093d self.assertIn( '

No content found

', output.data) - @patch('pagure.lib.decorators.admin_session_timedout') + @patch('pagure.decorators.admin_session_timedout') def test_change_ref_head(self,ast): """ Test the change_ref_head endpoint. """ ast.return_value = True @@ -4187,7 +4187,7 @@ index 0000000..fb7093d 'been uploaded', output.data) self.assertIn('This project has not been tagged.', output.data) - @patch('pagure.lib.decorators.admin_session_timedout') + @patch('pagure.decorators.admin_session_timedout') def test_add_token_all_tokens(self, ast): """ Test the add_token endpoint. """ ast.return_value = False @@ -4206,7 +4206,7 @@ index 0000000..fb7093d ) @patch.dict('pagure.config.config', {'USER_ACLS': ['create_project']}) - @patch('pagure.lib.decorators.admin_session_timedout') + @patch('pagure.decorators.admin_session_timedout') def test_add_token_one_token(self, ast): """ Test the add_token endpoint. """ ast.return_value = False @@ -4224,7 +4224,7 @@ index 0000000..fb7093d 1 ) - @patch('pagure.lib.decorators.admin_session_timedout') + @patch('pagure.decorators.admin_session_timedout') def test_add_token(self, ast): """ Test the add_token endpoint. """ ast.return_value = False @@ -4298,7 +4298,7 @@ index 0000000..fb7093d 'Valid until: ', output.data) - @patch('pagure.lib.decorators.admin_session_timedout') + @patch('pagure.decorators.admin_session_timedout') def test_revoke_api_token(self, ast): """ Test the revoke_api_token endpoint. """ ast.return_value = False diff --git a/tests/test_pagure_flask_ui_repo_delete_project.py b/tests/test_pagure_flask_ui_repo_delete_project.py index 838da74..0301aab 100644 --- a/tests/test_pagure_flask_ui_repo_delete_project.py +++ b/tests/test_pagure_flask_ui_repo_delete_project.py @@ -70,7 +70,7 @@ class PagureFlaskDeleteRepotests(tests.Modeltests): @patch.dict('pagure.config.config', {'ENABLE_DEL_PROJECTS': False}) @patch('pagure.lib.notify.send_email', MagicMock(return_value=True)) - @patch('pagure.ui.repo.admin_session_timedout', + @patch('pagure.decorators.admin_session_timedout', MagicMock(return_value=False)) def test_delete_repo_when_turned_off(self): """ Test the delete_repo endpoint for a fork when only deleting main @@ -86,7 +86,7 @@ class PagureFlaskDeleteRepotests(tests.Modeltests): self.assertEqual(len(projects), 4) @patch('pagure.lib.notify.send_email', MagicMock(return_value=True)) - @patch('pagure.ui.repo.admin_session_timedout', + @patch('pagure.decorators.admin_session_timedout', MagicMock(return_value=False)) def test_delete_button_present(self): """ Test that the delete button is present when deletions are @@ -105,7 +105,7 @@ class PagureFlaskDeleteRepotests(tests.Modeltests): @patch.dict('pagure.config.config', {'ENABLE_DEL_PROJECTS': False}) @patch('pagure.lib.notify.send_email', MagicMock(return_value=True)) - @patch('pagure.ui.repo.admin_session_timedout', + @patch('pagure.decorators.admin_session_timedout', MagicMock(return_value=False)) def test_delete_button_absent(self): """ Test that the delete button is absent when deletions are not @@ -125,7 +125,7 @@ class PagureFlaskDeleteRepotests(tests.Modeltests): @patch.dict('pagure.config.config', {'ENABLE_DEL_PROJECTS': False}) @patch.dict('pagure.config.config', {'ENABLE_DEL_FORKS': True}) @patch('pagure.lib.notify.send_email', MagicMock(return_value=True)) - @patch('pagure.ui.repo.admin_session_timedout', + @patch('pagure.decorators.admin_session_timedout', MagicMock(return_value=False)) def test_delete_fork_when_project_off_refreshing(self): """ Test the delete_repo endpoint for a fork when only deleting main @@ -156,7 +156,7 @@ class PagureFlaskDeleteRepotests(tests.Modeltests): @patch.dict('pagure.config.config', {'ENABLE_DEL_PROJECTS': False}) @patch.dict('pagure.config.config', {'ENABLE_DEL_FORKS': True}) @patch('pagure.lib.notify.send_email', MagicMock(return_value=True)) - @patch('pagure.ui.repo.admin_session_timedout', + @patch('pagure.decorators.admin_session_timedout', MagicMock(return_value=False)) def test_delete_fork_when_project_off(self): """ Test the delete_repo endpoint for a fork when only deleting main @@ -182,7 +182,7 @@ class PagureFlaskDeleteRepotests(tests.Modeltests): @patch.dict('pagure.config.config', {'ENABLE_DEL_PROJECTS': False}) @patch.dict('pagure.config.config', {'ENABLE_DEL_FORKS': False}) @patch('pagure.lib.notify.send_email', MagicMock(return_value=True)) - @patch('pagure.ui.repo.admin_session_timedout', + @patch('pagure.decorators.admin_session_timedout', MagicMock(return_value=False)) def test_delete_fork_when_fork_and_project_off(self): """ Test the delete_repo endpoint for a fork when deleting fork and @@ -201,7 +201,7 @@ class PagureFlaskDeleteRepotests(tests.Modeltests): @patch.dict('pagure.config.config', {'ENABLE_DEL_PROJECTS': False}) @patch.dict('pagure.config.config', {'ENABLE_DEL_FORKS': False}) @patch('pagure.lib.notify.send_email', MagicMock(return_value=True)) - @patch('pagure.ui.repo.admin_session_timedout', + @patch('pagure.decorators.admin_session_timedout', MagicMock(return_value=False)) def test_delete_fork_button_absent(self): """ Test that the delete button is absent when deletions are not @@ -223,7 +223,7 @@ class PagureFlaskDeleteRepotests(tests.Modeltests): @patch.dict('pagure.config.config', {'ENABLE_DEL_PROJECTS': False}) @patch.dict('pagure.config.config', {'ENABLE_DEL_FORKS': True}) @patch('pagure.lib.notify.send_email', MagicMock(return_value=True)) - @patch('pagure.ui.repo.admin_session_timedout', + @patch('pagure.decorators.admin_session_timedout', MagicMock(return_value=False)) def test_delete_fork_button_fork_del_allowed(self): """ Test that the delete button is present when deletions of projects @@ -253,7 +253,7 @@ class PagureFlaskDeleteRepotests(tests.Modeltests): @patch.dict('pagure.config.config', {'ENABLE_DEL_PROJECTS': False}) @patch.dict('pagure.config.config', {'ENABLE_DEL_FORKS': True}) @patch('pagure.lib.notify.send_email', MagicMock(return_value=True)) - @patch('pagure.ui.repo.admin_session_timedout', + @patch('pagure.decorators.admin_session_timedout', MagicMock(return_value=False)) def test_delete_fork_button_fork_del_allowed_read_only(self): """ Test that the delete button is absent when deletions of projects