From abf91efd5056c66036d0c8e69afefa604021684a Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Mar 03 2017 16:09:57 +0000 Subject: [PATCH 1/2] Add the endpoint and HTML allowing to delete a report in a project Fixes https://pagure.io/pagure/issue/1354 Relates to https://pagure.io/pagure/issue/2012 --- diff --git a/pagure/templates/settings.html b/pagure/templates/settings.html index a81abb8..713261b 100644 --- a/pagure/templates/settings.html +++ b/pagure/templates/settings.html @@ -934,6 +934,49 @@ + +
+
+
+ Reports +
+
+

+ Here is the list of reports saved for this project. +

+
+
    + {% for report in repo.reports %} +
  • + +   {{ report }} + +
    +
    + + {{ tag_form.csrf_token }} + +
    +
    +
  • + {% endfor %} +
+
+
{% endif %} {% if (config.get('ENABLE_TICKETS', True) diff --git a/pagure/ui/repo.py b/pagure/ui/repo.py index 96ba0ad..d24e35d 100644 --- a/pagure/ui/repo.py +++ b/pagure/ui/repo.py @@ -2575,3 +2575,55 @@ def update_custom_keys(repo, username=None, namespace=None): return flask.redirect(flask.url_for( 'view_settings', username=username, repo=repo.name, namespace=namespace)) + + +@APP.route('//delete/report', methods=['POST']) +@APP.route('///delete/report', methods=['POST']) +@APP.route('/fork///delete/report', methods=['POST']) +@APP.route( + '/fork////delete/report', + methods=['POST']) +@login_required +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( + '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 + if form.validate_on_submit(): + report = flask.request.form.get('report') + reports = repo.reports + if report not in reports: + flask.flash('Unknown report: %s' % report, 'error') + else: + del(reports[report]) + repo.reports = reports + try: + SESSION.add(repo) + SESSION.commit() + flask.flash('List of reports updated') + 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=namespace)) From 867895e80c0cd02233fde075db8df2cc1fe653d6 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Mar 03 2017 16:09:57 +0000 Subject: [PATCH 2/2] Add unit-tests for the delete_report endpoint --- diff --git a/tests/test_pagure_flask_ui_repo.py b/tests/test_pagure_flask_ui_repo.py index f37bdca..7725cf2 100644 --- a/tests/test_pagure_flask_ui_repo.py +++ b/tests/test_pagure_flask_ui_repo.py @@ -4146,6 +4146,209 @@ index 0000000..fb7093d '\n You are now' ' watching this repo.', output.data) + def test_delete_report(self): + """ Test the delete_report endpoint. """ + + output = self.app.post('/test/delete/report') + self.assertEqual(output.status_code, 404) + + tests.create_projects(self.session) + tests.create_projects_git(self.path, bare=True) + + user = tests.FakeUser() + user.username = 'pingou' + with tests.user_set(pagure.APP, user): + + output = self.app.get('/new/') + self.assertEqual(output.status_code, 200) + self.assertIn('Create new Project', output.data) + + csrf_token = output.data.split( + 'name="csrf_token" type="hidden" value="')[1].split('">')[0] + + # No report specified + data = { + 'csrf_token':csrf_token + } + output = self.app.post( + '/test/delete/report', data=data, follow_redirects=True) + self.assertEqual(output.status_code, 200) + self.assertIn( + '\n Unknown report: None', + output.data) + + # Report specified not in the project's reports + data = { + 'csrf_token':csrf_token, + 'report': 'foo' + } + output = self.app.post( + '/test/delete/report', data=data, follow_redirects=True) + self.assertEqual(output.status_code, 200) + self.assertIn( + '\n Unknown report: foo', + output.data) + + # Create a report + project = pagure.lib.get_project(self.session, name='test') + self.assertEqual(project.reports, {}) + name = 'test report' + url = '?foo=bar&baz=biz' + pagure.lib.save_report( + self.session, + repo=project, + name=name, + url=url, + username=None + ) + self.session.commit() + project = pagure.lib.get_project(self.session, name='test') + self.assertEqual( + project.reports, + {'test report': {'baz': 'biz', 'foo': 'bar'}} + ) + + # Missing CSRF + data = { + 'report': 'test report' + } + output = self.app.post( + '/test/delete/report', data=data, follow_redirects=True) + self.assertEqual(output.status_code, 200) + self.assertIn( + 'Settings - test - Pagure', + output.data) + + project = pagure.lib.get_project(self.session, name='test') + self.assertEqual( + project.reports, + {'test report': {'baz': 'biz', 'foo': 'bar'}} + ) + + # Delete the report + data = { + 'csrf_token':csrf_token, + 'report': 'test report' + } + output = self.app.post( + '/test/delete/report', data=data, follow_redirects=True) + self.assertEqual(output.status_code, 200) + self.assertIn( + '\n List of reports updated', + output.data) + project = pagure.lib.get_project(self.session, name='test') + self.assertEqual(project.reports, {}) + + def test_delete_report_ns_project(self): + """ Test the delete_report endpoint on a namespaced project. """ + + output = self.app.post('/foo/test/delete/report') + self.assertEqual(output.status_code, 404) + + tests.create_projects(self.session) + tests.create_projects_git(self.path, bare=True) + + user = tests.FakeUser() + user.username = 'pingou' + with tests.user_set(pagure.APP, user): + + output = self.app.get('/new/') + self.assertEqual(output.status_code, 200) + self.assertIn('Create new Project', output.data) + + csrf_token = output.data.split( + 'name="csrf_token" type="hidden" value="')[1].split('">')[0] + + item = pagure.lib.model.Project( + user_id=1, # pingou + namespace='foo', + name='test', + description='foo project #2', + hook_token='aaabbb', + ) + self.session.add(item) + self.session.commit() + gitrepo = os.path.join(self.path, 'foo', 'test.git') + pygit2.init_repository(gitrepo, bare=True) + + # No report specified + data = { + 'csrf_token':csrf_token + } + output = self.app.post( + '/foo/test/delete/report', data=data, follow_redirects=True) + self.assertEqual(output.status_code, 200) + self.assertIn( + '\n Unknown report: None', + output.data) + + # Report specified not in the project's reports + data = { + 'csrf_token':csrf_token, + 'report': 'foo' + } + output = self.app.post( + '/foo/test/delete/report', data=data, follow_redirects=True) + self.assertEqual(output.status_code, 200) + self.assertIn( + '\n Unknown report: foo', + output.data) + + # Create a report + project = pagure.lib.get_project( + self.session, name='test', namespace='foo') + self.assertEqual(project.reports, {}) + name = 'test report' + url = '?foo=bar&baz=biz' + pagure.lib.save_report( + self.session, + repo=project, + name=name, + url=url, + username=None + ) + self.session.commit() + project = pagure.lib.get_project( + self.session, name='test', namespace='foo') + self.assertEqual( + project.reports, + {'test report': {'baz': 'biz', 'foo': 'bar'}} + ) + + # Missing CSRF + data = { + 'report': 'test report' + } + output = self.app.post( + '/foo/test/delete/report', data=data, follow_redirects=True) + self.assertEqual(output.status_code, 200) + self.assertIn( + 'Settings - foo/test - Pagure', + output.data) + + project = pagure.lib.get_project( + self.session, name='test', namespace='foo') + self.assertEqual( + project.reports, + {'test report': {'baz': 'biz', 'foo': 'bar'}} + ) + + # Delete the report + data = { + 'csrf_token':csrf_token, + 'report': 'test report' + } + output = self.app.post( + '/foo/test/delete/report', data=data, follow_redirects=True) + self.assertEqual(output.status_code, 200) + self.assertIn( + '\n List of reports updated', + output.data) + + project = pagure.lib.get_project( + self.session, name='test', namespace='foo') + self.assertEqual(project.reports, {}) + + if __name__ == '__main__': - SUITE = unittest.TestLoader().loadTestsFromTestCase(PagureFlaskRepotests) - unittest.TextTestRunner(verbosity=2).run(SUITE) + unittest.main(verbosity=2)