diff --git a/pagure/lib/__init__.py b/pagure/lib/__init__.py index decf7a3..ca7e653 100644 --- a/pagure/lib/__init__.py +++ b/pagure/lib/__init__.py @@ -2473,6 +2473,7 @@ def search_issues( ) elif isinstance(private, basestring): user2 = aliased(model.User) + user4 = aliased(model.User) query = query.filter( sqlalchemy.or_( model.Issue.private == False, # noqa: E712 @@ -2480,6 +2481,11 @@ def search_issues( model.Issue.private == True, # noqa: E712 model.Issue.user_id == user2.id, user2.user == private, + ), + sqlalchemy.and_( + model.Issue.private == True, # noqa: E712 + model.Issue.assignee_id == user4.id, + user4.user == private, ) ) ) diff --git a/pagure/ui/issues.py b/pagure/ui/issues.py index c53f87d..afd5bea 100644 --- a/pagure/ui/issues.py +++ b/pagure/ui/issues.py @@ -1036,9 +1036,11 @@ def view_issue(repo, issueid, username=None, namespace=None): flask.abort(404, 'Issue not found') if issue.private: + assignee = issue.assignee.user if issue.assignee else None if not authenticated() or ( not flask.g.repo_committer - and issue.user.user != flask.g.fas_user.username): + and issue.user.user != flask.g.fas_user.username + and assignee != flask.g.fas_user.username): flask.abort(404, 'Issue not found') status = pagure.lib.get_issue_statuses(flask.g.session) diff --git a/tests/test_pagure_flask_ui_issues_private.py b/tests/test_pagure_flask_ui_issues_private.py new file mode 100644 index 0000000..892359f --- /dev/null +++ b/tests/test_pagure_flask_ui_issues_private.py @@ -0,0 +1,320 @@ +# -*- coding: utf-8 -*- + +""" + (c) 2018 - Copyright Red Hat Inc + + Authors: + Pierre-Yves Chibon + +""" + +import unittest +import sys +import os + +from mock import patch, MagicMock + +sys.path.insert(0, os.path.join(os.path.dirname( + os.path.abspath(__file__)), '..')) + +import pagure # noqa +import pagure.lib # noqa +import tests # noqa + + +class PagureFlaskIssuesPrivatetests(tests.Modeltests): + """ Tests for flask issues controller of pagure with private tickets + """ + + @patch('pagure.lib.notify.send_email', MagicMock(return_value=True)) + def setUp(self): + """ Set up the environnment, ran before every tests. """ + super(PagureFlaskIssuesPrivatetests, self).setUp() + + # Create a 3rd user + item = pagure.lib.model.User( + user='random', + fullname='Random user', + password='foo', + default_email='random@bar.com', + ) + self.session.add(item) + item = pagure.lib.model.UserEmail( + user_id=3, + email='random@bar.com') + self.session.add(item) + self.session.commit() + + tests.create_projects(self.session) + tests.create_projects_git(os.path.join(self.path, 'repos')) + + repo = pagure.lib.get_authorized_project(self.session, 'test') + msg = pagure.lib.new_issue( + session=self.session, + repo=repo, + title='Test issue #1', + content='We should work on this for the second time', + user='foo', + status='Open', + private=True, + ticketfolder=None + ) + self.session.commit() + self.assertEqual(msg.title, 'Test issue #1') + + msg = pagure.lib.new_issue( + session=self.session, + repo=repo, + title='Test issue #2', + content='We should work on this for the second time', + user='foo', + status='Open', + private=False, + ticketfolder=None + ) + self.session.commit() + self.assertEqual(msg.title, 'Test issue #2') + + def test_issue_list_anonymous(self): + """ Test the list of issues when user is logged out. """ + + output = self.app.get('/test/issues') + self.assertEqual(output.status_code, 200) + self.assertIn( + u'div class="projectinfo m-t-1 m-b-1">\ntest project #1' + u' ', output.data) + self.assertIn( + u'

\n 1 Open Issues', output.data) + + def test_issue_list_admin(self): + """ Test the list of issues when user is an admin of the project. + """ + + user = tests.FakeUser(username='pingou') + with tests.user_set(self.app.application, user): + output = self.app.get('/test/issues') + self.assertEqual(output.status_code, 200) + self.assertIn( + u'div class="projectinfo m-t-1 m-b-1">\ntest project #1' + u' ', output.data) + self.assertIn( + u'

\n 2 Open Issues', output.data) + + def test_issue_list_author(self): + """ Test the list of issues when user is an admin of the project. + """ + + user = tests.FakeUser(username='foo') + with tests.user_set(self.app.application, user): + output = self.app.get('/test/issues') + self.assertEqual(output.status_code, 200) + self.assertIn( + u'div class="projectinfo m-t-1 m-b-1">\ntest project #1' + u' ', output.data) + self.assertIn( + u'

\n 2 Open Issues', output.data) + + def test_issue_list_authenticated(self): + """ Test the list of issues when user is authenticated but has no + special access to the project. + """ + + user = tests.FakeUser(username='random') + with tests.user_set(self.app.application, user): + output = self.app.get('/test/issues') + self.assertEqual(output.status_code, 200) + self.assertIn( + u'div class="projectinfo m-t-1 m-b-1">\ntest project #1' + u' ', output.data) + self.assertIn( + u'

\n 1 Open Issues', output.data) + + def test_issue_list_authenticated_ticket(self): + """ Test the list of issues when user is authenticated but has + ticket level access to the project. + """ + repo = pagure.lib._get_project(self.session, 'test') + msg = pagure.lib.add_user_to_project( + session=self.session, + project=repo, + new_user='random', + user='pingou', + access='ticket', + ) + self.session.commit() + self.assertEqual(msg, 'User added') + + user = tests.FakeUser(username='random') + with tests.user_set(self.app.application, user): + output = self.app.get('/test/issues') + self.assertEqual(output.status_code, 200) + self.assertIn( + u'div class="projectinfo m-t-1 m-b-1">\ntest project #1' + u' ', output.data) + self.assertIn( + u'

\n 1 Open Issues', output.data) + + def test_issue_list_authenticated_commit(self): + """ Test the list of issues when user is authenticated but has + commit level access to the project. + """ + repo = pagure.lib._get_project(self.session, 'test') + msg = pagure.lib.add_user_to_project( + session=self.session, + project=repo, + new_user='random', + user='pingou', + access='commit', + ) + self.session.commit() + self.assertEqual(msg, 'User added') + + user = tests.FakeUser(username='random') + with tests.user_set(self.app.application, user): + output = self.app.get('/test/issues') + self.assertEqual(output.status_code, 200) + self.assertIn( + u'div class="projectinfo m-t-1 m-b-1">\ntest project #1' + u' ', output.data) + self.assertIn( + u'

\n 2 Open Issues', output.data) + + def test_issue_list_authenticated_assigned(self): + """ Test the list of issues when user is authenticated and is + assigned to one of the issue. + """ + + repo = pagure.lib._get_project(self.session, 'test') + issue = pagure.lib.search_issues(self.session, repo, issueid=1) + issue.assignee_id = 3 # random + self.session.add(issue) + self.session.commit() + + user = tests.FakeUser(username='random') + with tests.user_set(self.app.application, user): + output = self.app.get('/test/issues') + self.assertEqual(output.status_code, 200) + self.assertIn( + u'div class="projectinfo m-t-1 m-b-1">\ntest project #1' + u' ', output.data) + self.assertIn( + u'

\n 2 Open Issues', output.data) + + def test_view_issue_anonymous(self): + """ Test accessing a private ticket when user is logged out. """ + + output = self.app.get('/test/issue/1') + self.assertEqual(output.status_code, 404) + + def test_view_issue_admin(self): + """ Test accessing a private ticket when user is an admin of the + project. + """ + + user = tests.FakeUser(username='pingou') + with tests.user_set(self.app.application, user): + output = self.app.get('/test/issue/1') + self.assertEqual(output.status_code, 200) + self.assertIn( + u'div class="projectinfo m-t-1 m-b-1">\ntest project #1' + u' ', output.data) + self.assertIn( + u'Issue #1: Test issue #1 - test - Pagure', + output.data) + + def test_view_issue_author(self): + """ Test accessing a private ticket when user opened the ticket. + """ + + user = tests.FakeUser(username='foo') + with tests.user_set(self.app.application, user): + output = self.app.get('/test/issue/1') + self.assertEqual(output.status_code, 200) + self.assertIn( + u'div class="projectinfo m-t-1 m-b-1">\ntest project #1' + u' ', output.data) + self.assertIn( + u'Issue #1: Test issue #1 - test - Pagure', + output.data) + + def test_view_issue_authenticated(self): + """ Test accessing a private ticket when user is authenticated but + has no special access to the project. + """ + + user = tests.FakeUser(username='random') + with tests.user_set(self.app.application, user): + output = self.app.get('/test/issue/1') + self.assertEqual(output.status_code, 404) + + def test_view_issue_authenticated_ticket(self): + """ Test accessing a private ticket when user is authenticated and + has ticket level access to the project. + """ + repo = pagure.lib._get_project(self.session, 'test') + msg = pagure.lib.add_user_to_project( + session=self.session, + project=repo, + new_user='random', + user='pingou', + access='ticket', + ) + self.session.commit() + self.assertEqual(msg, 'User added') + + user = tests.FakeUser(username='random') + with tests.user_set(self.app.application, user): + output = self.app.get('/test/issue/1') + self.assertEqual(output.status_code, 404) + + def test_view_issue_authenticated_commit(self): + """ Test accessing a private ticket when user is authenticated and + has commit level access to the project. + """ + repo = pagure.lib._get_project(self.session, 'test') + msg = pagure.lib.add_user_to_project( + session=self.session, + project=repo, + new_user='random', + user='pingou', + access='commit', + ) + self.session.commit() + self.assertEqual(msg, 'User added') + + user = tests.FakeUser(username='random') + with tests.user_set(self.app.application, user): + output = self.app.get('/test/issue/1') + self.assertEqual(output.status_code, 200) + self.assertIn( + u'div class="projectinfo m-t-1 m-b-1">\ntest project #1' + u' ', output.data) + self.assertIn( + u'Issue #1: Test issue #1 - test - Pagure', + output.data) + + def test_view_issue_authenticated_assigned(self): + """ Test accessing a private ticket when user is authenticated and + is assigned to one of the issue. + """ + + repo = pagure.lib._get_project(self.session, 'test') + issue = pagure.lib.search_issues(self.session, repo, issueid=1) + issue.assignee_id = 3 # random + self.session.add(issue) + self.session.commit() + + user = tests.FakeUser(username='random') + with tests.user_set(self.app.application, user): + output = self.app.get('/test/issue/1') + self.assertEqual(output.status_code, 200) + self.assertIn( + u'div class="projectinfo m-t-1 m-b-1">\ntest project #1' + u' ', output.data) + self.assertIn( + u'Issue #1: Test issue #1 - test - Pagure', + output.data) + + +if __name__ == '__main__': + unittest.main(verbosity=2)