diff --git a/pagure/api/fork.py b/pagure/api/fork.py index 043833c..314fa27 100644 --- a/pagure/api/fork.py +++ b/pagure/api/fork.py @@ -509,7 +509,7 @@ def api_pull_request_add_comment( raise pagure.exceptions.APIError( 404, error_code=APIERROR.EPULLREQUESTSDISABLED) - if repo.fullname != flask.g.token.project.fullname: + if flask.g.token.project and repo != flask.g.token.project: raise pagure.exceptions.APIError(401, error_code=APIERROR.EINVALIDTOK) request = pagure.lib.search_pull_requests( @@ -646,14 +646,16 @@ def api_pull_request_add_flag(repo, requestid, username=None, namespace=None): output = {} if repo is None: - raise pagure.exceptions.APIError(404, error_code=APIERROR.ENOPROJECT) + raise pagure.exceptions.APIError( + 404, error_code=APIERROR.ENOPROJECT) if not repo.settings.get('pull_requests', True): raise pagure.exceptions.APIError( 404, error_code=APIERROR.EPULLREQUESTSDISABLED) - if repo.fullname != flask.g.token.project.fullname: - raise pagure.exceptions.APIError(401, error_code=APIERROR.EINVALIDTOK) + if flask.g.token.project and repo != flask.g.token.project: + raise pagure.exceptions.APIError( + 401, error_code=APIERROR.EINVALIDTOK) request = pagure.lib.search_pull_requests( SESSION, project_id=repo.id, requestid=requestid) diff --git a/pagure/api/issue.py b/pagure/api/issue.py index 63ee624..601869e 100644 --- a/pagure/api/issue.py +++ b/pagure/api/issue.py @@ -100,14 +100,16 @@ def api_new_issue(repo, username=None, namespace=None): output = {} if repo is None: - raise pagure.exceptions.APIError(404, error_code=APIERROR.ENOPROJECT) + raise pagure.exceptions.APIError( + 404, error_code=APIERROR.ENOPROJECT) if not repo.settings.get('issue_tracker', True): raise pagure.exceptions.APIError( 404, error_code=APIERROR.ETRACKERDISABLED) - if repo != flask.g.token.project: - raise pagure.exceptions.APIError(401, error_code=APIERROR.EINVALIDTOK) + if flask.g.token.project and repo != flask.g.token.project: + raise pagure.exceptions.APIError( + 401, error_code=APIERROR.EINVALIDTOK) user_obj = pagure.lib.get_user( SESSION, flask.g.fas_user.username) @@ -723,7 +725,7 @@ def api_comment_issue(repo, issueid, username=None, namespace=None): 404, error_code=APIERROR.ETRACKERDISABLED) if api_authenticated(): - if repo != flask.g.token.project: + if flask.g.token.project and repo != flask.g.token.project: raise pagure.exceptions.APIError( 401, error_code=APIERROR.EINVALIDTOK) diff --git a/tests/test_pagure_flask_api_fork.py b/tests/test_pagure_flask_api_fork.py index be8a3d7..c4c7a8c 100644 --- a/tests/test_pagure_flask_api_fork.py +++ b/tests/test_pagure_flask_api_fork.py @@ -670,6 +670,120 @@ class PagureFlaskApiForktests(tests.Modeltests): self.assertEqual(len(request.comments), 1) @patch('pagure.lib.notify.send_email') + def test_api_pull_request_add_comment_user_token(self, mockemail): + """ Test the api_pull_request_add_comment method of the flask api. """ + mockemail.return_value = True + + tests.create_projects(self.session) + tests.create_tokens(self.session, project_id=None) + tests.create_tokens_acl(self.session) + + headers = {'Authorization': 'token aaabbbcccddd'} + + # Invalid project + output = self.app.post( + '/api/0/foo/pull-request/1/comment', headers=headers) + self.assertEqual(output.status_code, 404) + data = json.loads(output.data) + self.assertDictEqual( + data, + { + "error": "Project not found", + "error_code": "ENOPROJECT", + } + ) + + # Valid token, invalid request + output = self.app.post( + '/api/0/test2/pull-request/1/comment', headers=headers) + self.assertEqual(output.status_code, 404) + data = json.loads(output.data) + self.assertDictEqual( + data, + { + "error": "Pull-Request not found", + "error_code": "ENOREQ", + } + ) + + # Valid token, invalid request in another project + output = self.app.post( + '/api/0/test/pull-request/1/comment', headers=headers) + self.assertEqual(output.status_code, 404) + data = json.loads(output.data) + self.assertDictEqual( + data, + { + "error": "Pull-Request not found", + "error_code": "ENOREQ", + } + ) + + # Create a pull-request + repo = pagure.lib.get_project(self.session, 'test') + forked_repo = pagure.lib.get_project(self.session, 'test') + req = pagure.lib.new_pull_request( + session=self.session, + repo_from=forked_repo, + branch_from='master', + repo_to=repo, + branch_to='master', + title='test pull-request', + user='pingou', + requestfolder=None, + ) + self.session.commit() + self.assertEqual(req.id, 1) + self.assertEqual(req.title, 'test pull-request') + + # Check comments before + request = pagure.lib.search_pull_requests( + self.session, project_id=1, requestid=1) + self.assertEqual(len(request.comments), 0) + + data = { + 'title': 'test issue', + } + + # Incomplete request + output = self.app.post( + '/api/0/test/pull-request/1/comment', data=data, headers=headers) + self.assertEqual(output.status_code, 400) + data = json.loads(output.data) + self.assertDictEqual( + data, + { + "error": "Invalid or incomplete input submited", + "error_code": "EINVALIDREQ", + "errors": {"comment": ["This field is required."]} + } + ) + + # No change + request = pagure.lib.search_pull_requests( + self.session, project_id=1, requestid=1) + self.assertEqual(len(request.comments), 0) + + data = { + 'comment': 'This is a very interesting question', + } + + # Valid request + output = self.app.post( + '/api/0/test/pull-request/1/comment', data=data, headers=headers) + self.assertEqual(output.status_code, 200) + data = json.loads(output.data) + self.assertDictEqual( + data, + {'message': 'Comment added'} + ) + + # One comment added + request = pagure.lib.search_pull_requests( + self.session, project_id=1, requestid=1) + self.assertEqual(len(request.comments), 1) + + @patch('pagure.lib.notify.send_email') def test_api_pull_request_add_flag(self, mockemail): """ Test the api_pull_request_add_flag method of the flask api. """ mockemail.return_value = True @@ -813,6 +927,154 @@ class PagureFlaskApiForktests(tests.Modeltests): self.assertEqual(request.flags[0].comment, 'Tests passed') self.assertEqual(request.flags[0].percent, 100) + @patch('pagure.lib.notify.send_email') + def test_api_pull_request_add_flag_user_token(self, mockemail): + """ Test the api_pull_request_add_flag method of the flask api. """ + mockemail.return_value = True + + tests.create_projects(self.session) + tests.create_tokens(self.session, project_id=None) + tests.create_tokens_acl(self.session) + + headers = {'Authorization': 'token aaabbbcccddd'} + + # Invalid project + output = self.app.post( + '/api/0/foo/pull-request/1/flag', headers=headers) + self.assertEqual(output.status_code, 404) + data = json.loads(output.data) + self.assertDictEqual( + data, + { + "error": "Project not found", + "error_code": "ENOPROJECT", + } + ) + + # Valid token, wrong project + output = self.app.post( + '/api/0/test2/pull-request/1/flag', headers=headers) + self.assertEqual(output.status_code, 404) + data = json.loads(output.data) + self.assertDictEqual( + data, + { + "error": "Pull-Request not found", + "error_code": "ENOREQ", + } + ) + + # No input + output = self.app.post( + '/api/0/test/pull-request/1/flag', headers=headers) + self.assertEqual(output.status_code, 404) + data = json.loads(output.data) + self.assertDictEqual( + data, + { + "error": "Pull-Request not found", + "error_code": "ENOREQ", + } + ) + + # Create a pull-request + repo = pagure.lib.get_project(self.session, 'test') + forked_repo = pagure.lib.get_project(self.session, 'test') + req = pagure.lib.new_pull_request( + session=self.session, + repo_from=forked_repo, + branch_from='master', + repo_to=repo, + branch_to='master', + title='test pull-request', + user='pingou', + requestfolder=None, + ) + self.session.commit() + self.assertEqual(req.id, 1) + self.assertEqual(req.title, 'test pull-request') + + # Check comments before + request = pagure.lib.search_pull_requests( + self.session, project_id=1, requestid=1) + self.assertEqual(len(request.flags), 0) + + data = { + 'username': 'Jenkins', + 'percent': 100, + 'url': 'http://jenkins.cloud.fedoraproject.org/', + 'uid': 'jenkins_build_pagure_100+seed', + } + + # Incomplete request + output = self.app.post( + '/api/0/test/pull-request/1/flag', data=data, headers=headers) + self.assertEqual(output.status_code, 400) + data = json.loads(output.data) + self.assertDictEqual( + data, + { + "error": "Invalid or incomplete input submited", + "error_code": "EINVALIDREQ", + "errors": {"comment": ["This field is required."]} + } + ) + + # No change + request = pagure.lib.search_pull_requests( + self.session, project_id=1, requestid=1) + self.assertEqual(len(request.flags), 0) + + data = { + 'username': 'Jenkins', + 'percent': 0, + 'comment': 'Tests failed', + 'url': 'http://jenkins.cloud.fedoraproject.org/', + 'uid': 'jenkins_build_pagure_100+seed', + } + + # Valid request + output = self.app.post( + '/api/0/test/pull-request/1/flag', data=data, headers=headers) + self.assertEqual(output.status_code, 200) + data = json.loads(output.data) + self.assertDictEqual( + data, + {'message': 'Flag added'} + ) + + # One flag added + request = pagure.lib.search_pull_requests( + self.session, project_id=1, requestid=1) + self.assertEqual(len(request.flags), 1) + self.assertEqual(request.flags[0].comment, 'Tests failed') + self.assertEqual(request.flags[0].percent, 0) + + # Update flag + data = { + 'username': 'Jenkins', + 'percent': 100, + 'comment': 'Tests passed', + 'url': 'http://jenkins.cloud.fedoraproject.org/', + 'uid': 'jenkins_build_pagure_100+seed', + } + + output = self.app.post( + '/api/0/test/pull-request/1/flag', data=data, headers=headers) + self.assertEqual(output.status_code, 200) + data = json.loads(output.data) + self.assertDictEqual( + data, + {'message': 'Flag updated'} + ) + + # One flag added + request = pagure.lib.search_pull_requests( + self.session, project_id=1, requestid=1) + self.assertEqual(len(request.flags), 1) + self.assertEqual(request.flags[0].comment, 'Tests passed') + self.assertEqual(request.flags[0].percent, 100) + if __name__ == '__main__': SUITE = unittest.TestLoader().loadTestsFromTestCase( diff --git a/tests/test_pagure_flask_api_issue.py b/tests/test_pagure_flask_api_issue.py index 9ac5544..18a6e66 100644 --- a/tests/test_pagure_flask_api_issue.py +++ b/tests/test_pagure_flask_api_issue.py @@ -486,6 +486,247 @@ class PagureFlaskApiIssuetests(tests.Modeltests): } ) + def test_api_new_issue_user_token(self): + """ Test the api_new_issue method of the flask api. """ + tests.create_projects(self.session) + tests.create_projects_git( + os.path.join(self.path, 'tickets'), bare=True) + tests.create_tokens(self.session, project_id=None) + tests.create_tokens_acl(self.session) + + headers = {'Authorization': 'token aaabbbcccddd'} + + # Valid token, invalid request - No input + output = self.app.post('/api/0/test2/new_issue', headers=headers) + self.assertEqual(output.status_code, 400) + data = json.loads(output.data) + self.assertDictEqual( + data, + { + "error": "Invalid or incomplete input submited", + "error_code": "EINVALIDREQ", + "errors": { + "issue_content": ["This field is required."], + "title": ["This field is required."], + } + } + ) + + # Another project, still an invalid request - No input + output = self.app.post('/api/0/test/new_issue', headers=headers) + self.assertEqual(output.status_code, 400) + data = json.loads(output.data) + self.assertDictEqual( + data, + { + "error": "Invalid or incomplete input submited", + "error_code": "EINVALIDREQ", + "errors": { + "issue_content": ["This field is required."], + "title": ["This field is required."], + } + } + ) + + data = { + 'title': 'test issue' + } + + # Invalid repo + output = self.app.post( + '/api/0/foo/new_issue', data=data, headers=headers) + self.assertEqual(output.status_code, 404) + data = json.loads(output.data) + self.assertDictEqual( + data, + { + "error": "Project not found", + "error_code": "ENOPROJECT", + } + ) + + # Incomplete request + output = self.app.post( + '/api/0/test/new_issue', data=data, headers=headers) + self.assertEqual(output.status_code, 400) + data = json.loads(output.data) + self.assertDictEqual( + data, + { + "error": "Invalid or incomplete input submited", + "error_code": "EINVALIDREQ", + "errors": { + "issue_content": ["This field is required."], + "title": ["This field is required."] + } + } + ) + + data = { + 'title': 'test issue', + 'issue_content': 'This issue needs attention', + } + + # Valid request + output = self.app.post( + '/api/0/test/new_issue', data=data, headers=headers) + self.assertEqual(output.status_code, 200) + data = json.loads(output.data) + data['issue']['date_created'] = '1431414800' + data['issue']['last_updated'] = '1431414800' + self.assertDictEqual( + data, + { + "issue": FULL_ISSUE_LIST[8], + "message": "Issue created" + } + ) + + # Valid request with milestone + data = { + 'title': 'test issue', + 'issue_content': 'This issue needs attention', + 'milestone': ['milestone-1.0'], + } + output = self.app.post( + '/api/0/test/new_issue', data=data, headers=headers) + self.assertEqual(output.status_code, 200) + data = json.loads(output.data) + data['issue']['date_created'] = '1431414800' + data['issue']['last_updated'] = '1431414800' + + self.assertDictEqual( + data, + { + "issue": FULL_ISSUE_LIST[7], + "message": "Issue created" + } + ) + + # Valid request, with private='false' + data = { + 'title': 'test issue', + 'issue_content': 'This issue needs attention', + 'private': 'false', + } + + output = self.app.post( + '/api/0/test/new_issue', data=data, headers=headers) + self.assertEqual(output.status_code, 200) + data = json.loads(output.data) + data['issue']['date_created'] = '1431414800' + data['issue']['last_updated'] = '1431414800' + self.assertDictEqual( + data, + { + "issue": FULL_ISSUE_LIST[6], + "message": "Issue created" + } + ) + + # Valid request, with private=False + data = { + 'title': 'test issue', + 'issue_content': 'This issue needs attention', + 'private': False + } + + output = self.app.post( + '/api/0/test/new_issue', data=data, headers=headers) + self.assertEqual(output.status_code, 200) + data = json.loads(output.data) + data['issue']['date_created'] = '1431414800' + data['issue']['last_updated'] = '1431414800' + self.assertDictEqual( + data, + { + "issue": FULL_ISSUE_LIST[5], + "message": "Issue created" + } + ) + + # Valid request, with private='False' + data = { + 'title': 'test issue', + 'issue_content': 'This issue needs attention', + 'private': 'False' + } + + output = self.app.post( + '/api/0/test/new_issue', data=data, headers=headers) + self.assertEqual(output.status_code, 200) + data = json.loads(output.data) + data['issue']['date_created'] = '1431414800' + data['issue']['last_updated'] = '1431414800' + self.assertDictEqual( + data, + { + "issue": FULL_ISSUE_LIST[4], + "message": "Issue created" + } + ) + + # Valid request, with private=0 + data = { + 'title': 'test issue', + 'issue_content': 'This issue needs attention', + 'private': 0 + } + + output = self.app.post( + '/api/0/test/new_issue', data=data, headers=headers) + self.assertEqual(output.status_code, 200) + data = json.loads(output.data) + data['issue']['date_created'] = '1431414800' + data['issue']['last_updated'] = '1431414800' + self.assertDictEqual( + data, + { + "issue": FULL_ISSUE_LIST[3], + "message": "Issue created" + } + ) + + # Private issue: True + data = { + 'title': 'test issue', + 'issue_content': 'This issue needs attention', + 'private': True, + } + output = self.app.post( + '/api/0/test/new_issue', data=data, headers=headers) + self.assertEqual(output.status_code, 200) + data = json.loads(output.data) + data['issue']['date_created'] = '1431414800' + data['issue']['last_updated'] = '1431414800' + self.assertDictEqual( + data, + { + "issue": FULL_ISSUE_LIST[2], + "message": "Issue created" + } + ) + + # Private issue: 1 + data = { + 'title': 'test issue1', + 'issue_content': 'This issue needs attention', + 'private': 1, + } + output = self.app.post( + '/api/0/test/new_issue', data=data, headers=headers) + self.assertEqual(output.status_code, 200) + data = json.loads(output.data) + data['issue']['date_created'] = '1431414800' + data['issue']['last_updated'] = '1431414800' + self.assertDictEqual( + data, + { + "issue": FULL_ISSUE_LIST[1], + "message": "Issue created" + } + ) + def test_api_view_issues(self): """ Test the api_view_issues method of the flask api. """ self.test_api_new_issue() @@ -1315,6 +1556,212 @@ class PagureFlaskApiIssuetests(tests.Modeltests): @patch('pagure.lib.git.update_git') @patch('pagure.lib.notify.send_email') + def test_api_comment_issue_user_token(self, p_send_email, p_ugt): + """ Test the api_comment_issue method of the flask api. """ + p_send_email.return_value = True + p_ugt.return_value = True + + tests.create_projects(self.session) + tests.create_tokens(self.session, project_id=None) + tests.create_tokens_acl(self.session) + + headers = {'Authorization': 'token aaabbbcccddd'} + + # Invalid project + output = self.app.post('/api/0/foo/issue/1/comment', headers=headers) + self.assertEqual(output.status_code, 404) + data = json.loads(output.data) + self.assertDictEqual( + data, + { + "error": "Project not found", + "error_code": "ENOPROJECT", + } + ) + + # Valid token, no issue on the project + output = self.app.post('/api/0/test2/issue/1/comment', headers=headers) + self.assertEqual(output.status_code, 404) + data = json.loads(output.data) + self.assertDictEqual( + data, + { + "error": "Issue not found", + "error_code": "ENOISSUE", + } + ) + + # Valid token, still no issue on this other project + output = self.app.post('/api/0/test/issue/1/comment', headers=headers) + self.assertEqual(output.status_code, 404) + data = json.loads(output.data) + self.assertDictEqual( + data, + { + "error": "Issue not found", + "error_code": "ENOISSUE", + } + ) + + # Create normal issue + repo = pagure.lib.get_project(self.session, 'test') + msg = pagure.lib.new_issue( + session=self.session, + repo=repo, + title='Test issue #1', + content='We should work on this', + user='pingou', + ticketfolder=None, + private=False, + issue_uid='aaabbbccc#1', + ) + self.session.commit() + self.assertEqual(msg.title, 'Test issue #1') + + # Check comments before + repo = pagure.lib.get_project(self.session, 'test') + issue = pagure.lib.search_issues(self.session, repo, issueid=1) + self.assertEqual(len(issue.comments), 0) + + data = { + 'title': 'test issue', + } + + # Incomplete request + output = self.app.post( + '/api/0/test/issue/1/comment', data=data, headers=headers) + self.assertEqual(output.status_code, 400) + data = json.loads(output.data) + self.assertDictEqual( + data, + { + "error": "Invalid or incomplete input submited", + "error_code": "EINVALIDREQ", + "errors": {"comment": ["This field is required."]} + } + ) + + # No change + repo = pagure.lib.get_project(self.session, 'test') + issue = pagure.lib.search_issues(self.session, repo, issueid=1) + self.assertEqual(issue.status, 'Open') + + data = { + 'comment': 'This is a very interesting question', + } + + # Valid request + output = self.app.post( + '/api/0/test/issue/1/comment', data=data, headers=headers) + self.assertEqual(output.status_code, 200) + data = json.loads(output.data) + self.assertDictEqual( + data, + {'message': 'Comment added'} + ) + + # One comment added + repo = pagure.lib.get_project(self.session, 'test') + issue = pagure.lib.search_issues(self.session, repo, issueid=1) + self.assertEqual(len(issue.comments), 1) + + # Create another project + item = pagure.lib.model.Project( + user_id=2, # foo + name='foo', + description='test project #3', + hook_token='aaabbbdddeee', + ) + self.session.add(item) + self.session.commit() + + # Create a token for pingou for this project + item = pagure.lib.model.Token( + id='pingou_foo', + user_id=1, + project_id=4, + expiration=datetime.datetime.utcnow() + datetime.timedelta( + days=30) + ) + self.session.add(item) + self.session.commit() + + # Give `issue_change_status` to this token when `issue_comment` + # is required + item = pagure.lib.model.TokenAcl( + token_id='pingou_foo', + acl_id=2, + ) + self.session.add(item) + self.session.commit() + + repo = pagure.lib.get_project(self.session, 'foo') + # Create private issue + msg = pagure.lib.new_issue( + session=self.session, + repo=repo, + title='Test issue', + content='We should work on this', + user='foo', + ticketfolder=None, + private=True, + issue_uid='aaabbbccc#2', + ) + self.session.commit() + self.assertEqual(msg.title, 'Test issue') + + # Check before + repo = pagure.lib.get_project(self.session, 'foo') + issue = pagure.lib.search_issues(self.session, repo, issueid=1) + self.assertEqual(len(issue.comments), 0) + + data = { + 'comment': 'This is a very interesting question', + } + headers = {'Authorization': 'token pingou_foo'} + + # Valid request but un-authorized + output = self.app.post( + '/api/0/foo/issue/1/comment', data=data, headers=headers) + self.assertEqual(output.status_code, 401) + data = json.loads(output.data) + self.assertEqual(pagure.api.APIERROR.EINVALIDTOK.name, + data['error_code']) + self.assertEqual(pagure.api.APIERROR.EINVALIDTOK.value, data['error']) + + # No comment added + repo = pagure.lib.get_project(self.session, 'foo') + issue = pagure.lib.search_issues(self.session, repo, issueid=1) + self.assertEqual(len(issue.comments), 0) + + # Create token for user foo + item = pagure.lib.model.Token( + id='foo_token2', + user_id=2, + project_id=4, + expiration=datetime.datetime.utcnow() + datetime.timedelta(days=30) + ) + self.session.add(item) + self.session.commit() + tests.create_tokens_acl(self.session, token_id='foo_token2') + + data = { + 'comment': 'This is a very interesting question', + } + headers = {'Authorization': 'token foo_token2'} + + # Valid request and authorized + output = self.app.post( + '/api/0/foo/issue/1/comment', data=data, headers=headers) + self.assertEqual(output.status_code, 200) + data = json.loads(output.data) + self.assertDictEqual( + data, + {'message': 'Comment added'} + ) + + @patch('pagure.lib.git.update_git') + @patch('pagure.lib.notify.send_email') def test_api_view_issue_comment(self, p_send_email, p_ugt): """ Test the api_view_issue_comment endpoint. """ p_send_email.return_value = True diff --git a/tests/test_pagure_flask_api_project.py b/tests/test_pagure_flask_api_project.py index 9e510a3..ea8fe6b 100644 --- a/tests/test_pagure_flask_api_project.py +++ b/tests/test_pagure_flask_api_project.py @@ -460,6 +460,96 @@ class PagureFlaskApiProjecttests(tests.Modeltests): ) @patch('pagure.lib.git.generate_gitolite_acls') + def test_api_new_project_user_token(self, p_gga): + """ Test the api_new_project method of the flask api. """ + p_gga.return_value = True + + tests.create_projects(self.session) + tests.create_projects_git(os.path.join(self.path, 'tickets')) + tests.create_tokens(self.session, project_id=None) + tests.create_tokens_acl(self.session) + + headers = {'Authorization': 'token foo_token'} + + # Invalid token + output = self.app.post('/api/0/new', headers=headers) + self.assertEqual(output.status_code, 401) + data = json.loads(output.data) + self.assertEqual(pagure.api.APIERROR.EINVALIDTOK.name, + data['error_code']) + self.assertEqual(pagure.api.APIERROR.EINVALIDTOK.value, data['error']) + + headers = {'Authorization': 'token aaabbbcccddd'} + + # No input + output = self.app.post('/api/0/new', headers=headers) + self.assertEqual(output.status_code, 400) + data = json.loads(output.data) + self.assertDictEqual( + data, + { + "error": "Invalid or incomplete input submited", + "error_code": "EINVALIDREQ", + "errors": { + "name": ["This field is required."], + "description": ["This field is required."] + } + } + ) + + data = { + 'name': 'test', + } + + # Incomplete request + output = self.app.post( + '/api/0/new', data=data, headers=headers) + self.assertEqual(output.status_code, 400) + data = json.loads(output.data) + self.assertDictEqual( + data, + { + "error": "Invalid or incomplete input submited", + "error_code": "EINVALIDREQ", + "errors": {"description": ["This field is required."]} + } + ) + + data = { + 'name': 'test', + 'description': 'Just a small test project', + } + + # Valid request but repo already exists + output = self.app.post( + '/api/0/new/', data=data, headers=headers) + self.assertEqual(output.status_code, 400) + data = json.loads(output.data) + self.assertDictEqual( + data, + { + "error": "The project repo \"test\" already exists " + "in the database", + "error_code": "ENOCODE" + } + ) + + data = { + 'name': 'test_42', + 'description': 'Just another small test project', + } + + # Valid request + output = self.app.post( + '/api/0/new/', data=data, headers=headers) + self.assertEqual(output.status_code, 200) + data = json.loads(output.data) + self.assertDictEqual( + data, + {'message': 'Project "test_42" created'} + ) + + @patch('pagure.lib.git.generate_gitolite_acls') def test_api_new_project_user_ns(self, p_gga): """ Test the api_new_project method of the flask api. """ pagure.APP.config['USER_NAMESPACE'] = True @@ -632,6 +722,130 @@ class PagureFlaskApiProjecttests(tests.Modeltests): } ) + @patch('pagure.lib.git.generate_gitolite_acls') + def test_api_fork_project_user_token(self, p_gga): + """ Test the api_fork_project method of the flask api. """ + p_gga.return_value = True + + tests.create_projects(self.session) + for folder in ['docs', 'tickets', 'requests', 'repos']: + tests.create_projects_git( + os.path.join(self.path, folder), bare=True) + tests.create_tokens(self.session, project_id=None) + tests.create_tokens_acl(self.session) + + headers = {'Authorization': 'token foo_token'} + + # Invalid token + output = self.app.post('/api/0/fork', headers=headers) + self.assertEqual(output.status_code, 401) + data = json.loads(output.data) + self.assertEqual(pagure.api.APIERROR.EINVALIDTOK.name, + data['error_code']) + self.assertEqual(pagure.api.APIERROR.EINVALIDTOK.value, data['error']) + + headers = {'Authorization': 'token aaabbbcccddd'} + + # No input + output = self.app.post('/api/0/fork', headers=headers) + self.assertEqual(output.status_code, 400) + data = json.loads(output.data) + self.assertDictEqual( + data, + { + "error": "Invalid or incomplete input submited", + "error_code": "EINVALIDREQ", + "errors": {"repo": ["This field is required."]} + } + ) + + data = { + 'name': 'test', + } + + # Incomplete request + output = self.app.post( + '/api/0/fork', data=data, headers=headers) + self.assertEqual(output.status_code, 400) + data = json.loads(output.data) + self.assertDictEqual( + data, + { + "error": "Invalid or incomplete input submited", + "error_code": "EINVALIDREQ", + "errors": {"repo": ["This field is required."]} + } + ) + + data = { + 'repo': 'test', + } + + # Valid request + output = self.app.post( + '/api/0/fork/', data=data, headers=headers) + self.assertEqual(output.status_code, 200) + data = json.loads(output.data) + self.assertDictEqual( + data, + { + "message": "Repo \"test\" cloned to \"pingou/test\"" + } + ) + + data = { + 'repo': 'test', + } + + # project already forked + output = self.app.post( + '/api/0/fork/', data=data, headers=headers) + self.assertEqual(output.status_code, 400) + data = json.loads(output.data) + self.assertDictEqual( + data, + { + "error": "Repo \"forks/pingou/test\" already exists", + "error_code": "ENOCODE" + } + ) + + data = { + 'repo': 'test', + 'username': 'pingou', + } + + # Fork already exists + output = self.app.post( + '/api/0/fork/', data=data, headers=headers) + self.assertEqual(output.status_code, 400) + data = json.loads(output.data) + self.assertDictEqual( + data, + { + "error": "Repo \"forks/pingou/test\" already exists", + "error_code": "ENOCODE" + } + ) + + data = { + 'repo': 'test', + 'namespace': 'pingou', + } + + # Repo does not exists + output = self.app.post( + '/api/0/fork/', data=data, headers=headers) + self.assertEqual(output.status_code, 404) + data = json.loads(output.data) + self.assertDictEqual( + data, + { + "error": "Project not found", + "error_code": "ENOPROJECT" + } + ) + if __name__ == '__main__': SUITE = unittest.TestLoader().loadTestsFromTestCase( PagureFlaskApiProjecttests)