diff --git a/alembic/versions/e4dbfcd20f42_add_default_priority_to_projects.py b/alembic/versions/e4dbfcd20f42_add_default_priority_to_projects.py new file mode 100644 index 0000000..650a0c9 --- /dev/null +++ b/alembic/versions/e4dbfcd20f42_add_default_priority_to_projects.py @@ -0,0 +1,28 @@ +"""Add default_priority to projects + +Revision ID: e4dbfcd20f42 +Revises: 21292448a775 +Create Date: 2017-10-20 13:34:01.323657 + +""" + +# revision identifiers, used by Alembic. +revision = 'e4dbfcd20f42' +down_revision = '21292448a775' + + +from alembic import op +import sqlalchemy as sa + + +def upgrade(): + ''' Add default_priority column to projects table''' + + op.add_column( + 'projects', + sa.Column('default_priority', sa.Text, nullable=True) + ) + +def downgrade(): + ''' Revert the default_priority column added''' + op.drop_column('projects', 'default_priority') diff --git a/pagure/forms.py b/pagure/forms.py index e784597..a07b8f3 100644 --- a/pagure/forms.py +++ b/pagure/forms.py @@ -664,6 +664,26 @@ class DefaultBranchForm(PagureForm): ] +class DefaultPriorityForm(PagureForm): + """Form to change the default priority for a repository""" + priority = wtforms.SelectField( + 'default_priority', + [wtforms.validators.optional()], + choices=[] + ) + + def __init__(self, *args, **kwargs): + """ Calls the default constructor with the normal argument but + uses the list of collection provided to fill the choices of the + drop-down list. + """ + super(DefaultPriorityForm, self).__init__(*args, **kwargs) + if 'priorities' in kwargs: + self.priority.choices = [ + (priority, priority) for priority in kwargs['priorities'] + ] + + class EditCommentForm(PagureForm): """ Form to verify that comment is not empty """ diff --git a/pagure/lib/model.py b/pagure/lib/model.py index 81f2390..5df8631 100644 --- a/pagure/lib/model.py +++ b/pagure/lib/model.py @@ -374,6 +374,7 @@ class Project(BASE): ), nullable=True) _priorities = sa.Column(sa.Text, nullable=True) + default_priority = sa.Column(sa.Text, nullable=True) _milestones = sa.Column(sa.Text, nullable=True) _quick_replies = sa.Column(sa.Text, nullable=True) _reports = sa.Column(sa.Text, nullable=True) diff --git a/pagure/templates/settings.html b/pagure/templates/settings.html index 0eafd21..aa2ea17 100644 --- a/pagure/templates/settings.html +++ b/pagure/templates/settings.html @@ -590,6 +590,7 @@ and repo.settings.get('issue_tracker', True) %}
+
Priorities
@@ -657,6 +658,47 @@
+ + {% if repo.priorities %} +
+ Default Priority +
+
+

+ The default priority will be set to all issues created after + it has been set. +

+
+ +
+ {{ tag_form.csrf_token }} +
+
+
+ Default priority +
+
+
+ {{ priority_form.priority(class_="c-select") }} +
+ +
+
+ +
+
+
+
+ {% endif %} + diff --git a/pagure/ui/repo.py b/pagure/ui/repo.py index d79c370..e7751f5 100644 --- a/pagure/ui/repo.py +++ b/pagure/ui/repo.py @@ -1035,6 +1035,9 @@ def view_settings(repo, username=None, namespace=None): branches = repo_obj.listall_branches() branches_form = pagure.forms.DefaultBranchForm(branches=branches) + priority_form = pagure.forms.DefaultPriorityForm( + priorities=repo.priorities.values()) + if form.validate_on_submit(): settings = {} for key in flask.request.form: @@ -1068,6 +1071,7 @@ def view_settings(repo, username=None, namespace=None): if flask.request.method == 'GET' and branchname: branches_form.branches.data = branchname + priority_form.priorities.data = repo.default_priority return flask.render_template( 'settings.html', @@ -1079,6 +1083,7 @@ def view_settings(repo, username=None, namespace=None): form=form, tag_form=tag_form, branches_form=branches_form, + priority_form=priority_form, tags=tags, plugins=plugins, branchname=branchname, @@ -1281,6 +1286,57 @@ def update_priorities(repo, username=None, namespace=None): namespace=repo.namespace)) +@APP.route('//update/default_priority', methods=['POST']) +@APP.route('///update/default_priority', methods=['POST']) +@APP.route('/fork///update/default_priority', methods=['POST']) +@APP.route( + '/fork////update/default_priority', + methods=['POST']) +@login_required +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( + '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()) + + if form.validate_on_submit(): + priority = form.priority.data or None + if priority in repo.priorities.values() or priority is None: + repo.default_priority = priority + try: + SESSION.add(repo) + SESSION.commit() + if priority: + flask.flash('Default priority set to %s' % priority) + else: + flask.flash('Default priority reset') + except SQLAlchemyError as err: # pragma: no cover + SESSION.rollback() + flask.flash(str(err), 'error') + + return flask.redirect(flask.url_for( + 'view_settings', username=username, repo=repo.name, + namespace=repo.namespace)) + + @APP.route('//update/milestones', methods=['POST']) @APP.route('///update/milestones', methods=['POST']) @APP.route('/fork///update/milestones', methods=['POST']) diff --git a/tests/test_pagure_flask_ui_priorities.py b/tests/test_pagure_flask_ui_priorities.py index 762e9a8..493c8f0 100644 --- a/tests/test_pagure_flask_ui_priorities.py +++ b/tests/test_pagure_flask_ui_priorities.py @@ -20,7 +20,7 @@ import tempfile import os import pygit2 -from mock import patch +from mock import patch, MagicMock sys.path.insert(0, os.path.join(os.path.dirname( os.path.abspath(__file__)), '..')) @@ -444,6 +444,140 @@ class PagureFlaskPrioritiestests(tests.Modeltests): repo = pagure.lib._get_project(self.session, 'test') self.assertEqual(repo.priorities, {}) + @patch('pagure.lib.git.update_git', MagicMock(return_value=True)) + @patch('pagure.lib.notify.send_email', MagicMock(return_value=True)) + def test_default_priority(self): + """ Test updating the default priority of a repo. """ + tests.create_projects(self.session) + tests.create_projects_git(os.path.join(self.path, 'repos'), bare=True) + + # Check the default priorities + repo = pagure.get_authorized_project(self.session, 'test') + self.assertEqual(repo.priorities, {}) + self.assertEqual(repo.default_priority, None) + + user = tests.FakeUser() + user.username = 'pingou' + with tests.user_set(pagure.APP, user): + + csrf_token = self.get_csrf() + + # Set some priorities + data = { + 'priority_weigth': [1, 2, 3], + 'priority_title': ['High', 'Normal', 'Low'], + 'csrf_token': csrf_token, + } + output = self.app.post( + '/test/update/priorities', data=data, follow_redirects=True) + self.assertEqual(output.status_code, 200) + # Check the redirect + self.assertIn( + 'Settings - test - Pagure', output.data) + self.assertIn('

Settings for test

', output.data) + # Check the ordering + self.assertTrue( + output.data.find('High') < output.data.find('Normal')) + self.assertTrue( + output.data.find('Normal') < output.data.find('Low')) + # Check the result of the action -- Priority recorded + repo = pagure.get_authorized_project(self.session, 'test') + self.assertEqual( + repo.priorities, + {u'': u'', u'1': u'High', u'2': u'Normal', u'3': u'Low'} + ) + + # Try setting the default priority -- no csrf + data = {'priority': 'High'} + output = self.app.post( + '/test/update/default_priority', data=data, + follow_redirects=True) + self.assertEqual(output.status_code, 200) + # Check the redirect + self.assertIn( + 'Settings - test - Pagure', output.data) + self.assertIn('

Settings for test

', output.data) + # Check the result of the action -- default_priority no change + repo = pagure.get_authorized_project(self.session, 'test') + self.assertEqual(repo.default_priority, None) + + # Try setting the default priority + data = {'priority': 'High', 'csrf_token': csrf_token} + output = self.app.post( + '/test/update/default_priority', data=data, + follow_redirects=True) + self.assertEqual(output.status_code, 200) + # Check the redirect + self.assertIn( + 'Settings - test - Pagure', output.data) + self.assertIn('

Settings for test

', output.data) + self.assertIn( + '\n Default priority set ' + 'to High', output.data) + # Check the result of the action -- default_priority no change + repo = pagure.get_authorized_project(self.session, 'test') + self.assertEqual(repo.default_priority, 'High') + + # Try setting a wrong default priority + data = {'priority': 'Smooth', 'csrf_token': csrf_token} + output = self.app.post( + '/test/update/default_priority', data=data, + follow_redirects=True) + self.assertEqual(output.status_code, 200) + # Check the redirect + self.assertIn( + 'Settings - test - Pagure', output.data) + self.assertIn('

Settings for test

', output.data) + # Check the result of the action -- default_priority no change + repo = pagure.get_authorized_project(self.session, 'test') + self.assertEqual(repo.default_priority, 'High') + + # reset the default priority + data = {'csrf_token': csrf_token, 'priority': ''} + output = self.app.post( + '/test/update/default_priority', data=data, + follow_redirects=True) + self.assertEqual(output.status_code, 200) + # Check the redirect + self.assertIn( + 'Settings - test - Pagure', output.data) + self.assertIn('

Settings for test

', output.data) + self.assertIn( + '\n Default priority reset', + output.data) + # Check the result of the action -- default_priority no change + repo = pagure.get_authorized_project(self.session, 'test') + self.assertEqual(repo.default_priority, None) + + # Check the behavior if the project disabled the issue tracker + settings = repo.settings + settings['issue_tracker'] = False + repo.settings = settings + self.session.add(repo) + self.session.commit() + + output = self.app.post( + '/test/update/default_priority', data=data) + self.assertEqual(output.status_code, 404) + + # Check for an invalid project + output = self.app.post( + '/foo/update/default_priority', data=data) + self.assertEqual(output.status_code, 404) + + # Check for a non-admin user + settings = repo.settings + settings['issue_tracker'] = True + repo.settings = settings + self.session.add(repo) + self.session.commit() + + user.username = 'ralph' + with tests.user_set(pagure.APP, user): + output = self.app.post( + '/test/update/default_priority', data=data) + self.assertEqual(output.status_code, 403) + if __name__ == '__main__': unittest.main(verbosity=2)