From 0f9ac5ab0880cf13d7f07a545a7cd0709ae87688 Mon Sep 17 00:00:00 2001 From: mprahl Date: Aug 29 2017 20:40:41 +0000 Subject: Support both JSON and Form POST on APIs that accepted only JSON --- diff --git a/pagure/api/project.py b/pagure/api/project.py index 2d0798b..1700a20 100644 --- a/pagure/api/project.py +++ b/pagure/api/project.py @@ -919,19 +919,24 @@ def api_modify_project(repo, namespace=None): 401, error_code=APIERROR.EMODIFYPROJECTNOTALLOWED) valid_keys = ['main_admin'] - # Set force to True to ignore the mimetype. Set silent so that None is - # returned if it's invalid JSON. - json = flask.request.get_json(force=True, silent=True) - if not json: + # Check if it's JSON or form data + if flask.request.headers.get('Content-Type') == 'application/json': + # Set force to True to ignore the mimetype. Set silent so that None is + # returned if it's invalid JSON. + args = flask.request.get_json(force=True, silent=True) or {} + else: + args = flask.request.form + + if not args: raise pagure.exceptions.APIError(400, error_code=APIERROR.EINVALIDREQ) # Check to make sure there aren't parameters we don't support - for key in json.keys(): + for key in args.keys(): if key not in valid_keys: raise pagure.exceptions.APIError( 400, error_code=APIERROR.EINVALIDREQ) - if 'main_admin' in json: + if 'main_admin' in args: if flask.g.fas_user != project.user and not is_site_admin: raise pagure.exceptions.APIError( 401, error_code=APIERROR.ENOTMAINADMIN) @@ -940,7 +945,7 @@ def api_modify_project(repo, namespace=None): return flask.jsonify(project.to_json(public=False, api=True)) try: - new_main_admin = pagure.lib.get_user(SESSION, json['main_admin']) + new_main_admin = pagure.lib.get_user(SESSION, args['main_admin']) except pagure.exceptions.PagureException: raise pagure.exceptions.APIError(400, error_code=APIERROR.ENOUSER) @@ -1119,10 +1124,14 @@ def api_generate_acls(repo, username=None, namespace=None): if not project: raise pagure.exceptions.APIError(404, error_code=APIERROR.ENOPROJECT) - # Set force to True to ignore the mimetype. Set silent so that None is - # returned if it's invalid JSON. - json = flask.request.get_json(force=True, silent=True) or {} - wait = json.get('wait', False) + # Check if it's JSON or form data + if flask.request.headers.get('Content-Type') == 'application/json': + # Set force to True to ignore the mimetype. Set silent so that None is + # returned if it's invalid JSON. + json = flask.request.get_json(force=True, silent=True) or {} + wait = json.get('wait', False) + else: + wait = str(flask.request.form.get('wait')).lower() in ['true', '1'] try: taskid = pagure.lib.git.generate_gitolite_acls( diff --git a/tests/test_pagure_flask_api_project.py b/tests/test_pagure_flask_api_project.py index 9509e37..59766c7 100644 --- a/tests/test_pagure_flask_api_project.py +++ b/tests/test_pagure_flask_api_project.py @@ -1130,6 +1130,68 @@ class PagureFlaskApiProjecttests(tests.Modeltests): with tests.user_set(pagure.APP, user): output = self.app.patch( '/api/0/test', headers=headers, + data={'main_admin': 'foo'}) + self.assertEqual(output.status_code, 200) + data = json.loads(output.data) + data['date_created'] = '1496338274' + data['date_modified'] = '1496338274' + expected_output = { + "access_groups": { + "admin": [], + "commit": [], + "ticket": [] + }, + "access_users": { + "admin": [], + "commit": [], + "owner": [ + "foo" + ], + "ticket": [] + }, + "close_status": [ + "Invalid", + "Insufficient data", + "Fixed", + "Duplicate" + ], + "custom_keys": [], + "date_created": "1496338274", + "date_modified": "1496338274", + "description": "test project #1", + "fullname": "test", + "id": 1, + "milestones": {}, + "name": "test", + "namespace": None, + "parent": None, + "priorities": {}, + "tags": [], + "user": { + "default_email": "foo@bar.com", + "emails": [ + "foo@bar.com" + ], + "fullname": "foo bar", + "name": "foo" + } + } + self.assertEqual(data, expected_output) + + def test_api_modify_project_main_admin_json(self): + """ Test the api_modify_project method of the flask api when the + request is to change the main_admin of the project using JSON. """ + tests.create_projects(self.session) + tests.create_tokens(self.session, project_id=None) + tests.create_tokens_acl(self.session, 'aaabbbcccddd', 'modify_project') + headers = {'Authorization': 'token aaabbbcccddd', + 'Content-Type': 'application/json'} + + user = pagure.lib.get_user(self.session, 'pingou') + user.cla_done = True + with tests.user_set(pagure.APP, user): + output = self.app.patch( + '/api/0/test', headers=headers, data=json.dumps({'main_admin': 'foo'})) self.assertEqual(output.status_code, 200) data = json.loads(output.data) @@ -1193,7 +1255,7 @@ class PagureFlaskApiProjecttests(tests.Modeltests): with tests.user_set(pagure.APP, user): output = self.app.patch( '/api/0/test', headers=headers, - data=json.dumps({'main_admin': 'foo'})) + data={'main_admin': 'foo'}) self.assertEqual(output.status_code, 200) data = json.loads(output.data) data['date_created'] = '1496338274' @@ -1263,7 +1325,7 @@ class PagureFlaskApiProjecttests(tests.Modeltests): with tests.user_set(pagure.APP, user): output = self.app.patch( '/api/0/test', headers=headers, - data=json.dumps({'main_admin': 'foo'})) + data={'main_admin': 'foo'}) self.assertEqual(output.status_code, 401) expected_error = { 'error': ('Only the main admin can set the main admin of a ' @@ -1286,7 +1348,7 @@ class PagureFlaskApiProjecttests(tests.Modeltests): with tests.user_set(pagure.APP, user): output = self.app.patch( '/api/0/test', headers=headers, - data=json.dumps({'main_admin': 'foo'})) + data={'main_admin': 'foo'}) self.assertEqual(output.status_code, 401) expected_error = { 'error': 'You are not allowed to modify this project', @@ -1330,7 +1392,7 @@ class PagureFlaskApiProjecttests(tests.Modeltests): with tests.user_set(pagure.APP, user): output = self.app.patch( '/api/0/test', headers=headers, - data=json.dumps({'invalid': 'invalid'})) + data={'invalid': 'invalid'}) self.assertEqual(output.status_code, 400) expected_error = { 'error': 'Invalid or incomplete input submited', @@ -1353,7 +1415,7 @@ class PagureFlaskApiProjecttests(tests.Modeltests): with tests.user_set(pagure.APP, user): output = self.app.patch( '/api/0/test', headers=headers, - data=json.dumps({'main_admin': 'tbrady'})) + data={'main_admin': 'tbrady'}) self.assertEqual(output.status_code, 400) expected_error = { 'error': 'No such user found', @@ -2121,6 +2183,35 @@ class PagureFlaskApiProjecttests(tests.Modeltests): with tests.user_set(pagure.APP, user): output = self.app.post( '/api/0/test/git/generateacls', headers=headers, + data={'wait': False}) + self.assertEqual(output.status_code, 200) + data = json.loads(output.data) + expected_output = { + 'message': 'Project ACL generation queued', + 'taskid': 'abc-1234' + } + self.assertEqual(data, expected_output) + mock_gen_acls.assert_called_once_with( + name='test', namespace=None, user=None, group=None) + + @patch('pagure.lib.tasks.generate_gitolite_acls.delay') + def test_api_generate_acls_json(self, mock_gen_acls): + """ Test the api_generate_acls method of the flask api using JSON """ + tests.create_projects(self.session) + tests.create_tokens(self.session, project_id=None) + tests.create_tokens_acl( + self.session, 'aaabbbcccddd', 'generate_acls_project') + headers = {'Authorization': 'token aaabbbcccddd', + 'Content-Type': 'application/json'} + + mock_gen_acls_rv = Mock() + mock_gen_acls_rv.id = 'abc-1234' + mock_gen_acls.return_value = mock_gen_acls_rv + + user = pagure.lib.get_user(self.session, 'pingou') + with tests.user_set(pagure.APP, user): + output = self.app.post( + '/api/0/test/git/generateacls', headers=headers, data=json.dumps({'wait': False})) self.assertEqual(output.status_code, 200) data = json.loads(output.data) @@ -2154,7 +2245,7 @@ class PagureFlaskApiProjecttests(tests.Modeltests): with tests.user_set(pagure.APP, user): output = self.app.post( '/api/0/test/git/generateacls', headers=headers, - data=json.dumps({'wait': True})) + data={'wait': True}) self.assertEqual(output.status_code, 200) data = json.loads(output.data) expected_output = { @@ -2178,7 +2269,7 @@ class PagureFlaskApiProjecttests(tests.Modeltests): with tests.user_set(pagure.APP, user): output = self.app.post( '/api/0/test12345123/git/generateacls', headers=headers, - data=json.dumps({'wait': False})) + data={'wait': False}) self.assertEqual(output.status_code, 404) data = json.loads(output.data) expected_output = {