From 0bf7de9bfcaa7885bca3aa5fa34a1f752d920c01 Mon Sep 17 00:00:00 2001 From: Fabien Boucher Date: Feb 11 2019 10:11:57 +0000 Subject: [PATCH 1/9] Add project createapitoken endpoint A project owner or admin (with the 'modify_project') acl can ask the creation of a project user token. The token description and acl can be passed to the endpoint. The endpoint return the token id and the description. --- diff --git a/pagure/api/project.py b/pagure/api/project.py index 2f3b159..83ab5b3 100644 --- a/pagure/api/project.py +++ b/pagure/api/project.py @@ -2133,3 +2133,109 @@ def api_modify_project_options(repo, username=None, namespace=None): raise pagure.exceptions.APIError(400, error_code=APIERROR.EDBERROR) return flask.jsonify({"message": message, "status": "ok"}) + +@API.route("//createapitoken", methods=["POST"]) +@API.route("///createapitoken", methods=["POST"]) +@API.route("/fork///createapitoken", methods=["POST"]) +@API.route( + "/fork////createapitoken", methods=["POST"] +) +@api_login_required(acls=["modify_project"]) +@api_method +def api_project_create_api_token(repo, namespace=None, username=None): + """ + Create API project Token + ------------------------ + Create a project token API for the caller user + + This is restricted to project admins. + + :: + + POST /api/0//createapitoken + POST /api/0///createapitoken + + :: + + POST /api/0/fork///createapitoken + POST /api/0/fork////createapitoken + + + Input + ^^^^^ + + +------------------+---------+---------------+---------------------------+ + | Key | Type | Optionality | Description | + +==================+=========+===============+===========================+ + | ``desc`` | String | Mandatory | A string to specify the | + | | | | description of the token | + | | | | | + +------------------+---------+---------------+---------------------------+ + | ``acl`` | String | Mandatory | The ACL as a comma | + | | | | string | + | | | | | + +------------------+---------+---------------+---------------------------+ + + + Sample response + ^^^^^^^^^^^^^^^ + + :: + + { + "token": { + "description": "My foo token", + "id": "aaabbbcccfootoken", + }, + } + + """ + output = {} + project = get_authorized_api_project( + flask.g.session, repo, namespace=namespace + ) + if not project: + raise pagure.exceptions.APIError(404, error_code=APIERROR.ENOPROJECT) + + if flask.g.token.project and project != flask.g.token.project: + raise pagure.exceptions.APIError(401, error_code=APIERROR.EINVALIDTOK) + + + authorized_users = [project.user.username] + authorized_users.extend( + [user.user for user in project.access_users['admin']]) + if flask.g.fas_user.user not in authorized_users: + raise pagure.exceptions.APIError( + 401, error_code=APIERROR.ENOTHIGHENOUGH) + + + form = flask.request.form + valid_form = True + description = form.get('description') + acl = form.get('acl') + if not isinstance(description, str) or not isinstance(acl, str): + valid_form = False + acl_list = acl.split(',') + for ac in acl_list: + if ac not in pagure_config.get("ACLS", []): + valid_form = False + break + if not valid_form: + raise pagure.exceptions.APIError( + 400, error_code=APIERROR.EINVALIDREQ) + + pagure.lib.query.add_token_to_user( + flask.g.session, project, acl.split(','), flask.g.fas_user.user, + description) + token_id = pagure.lib.query.search_token( + flask.g.session, None, user=flask.g.fas_user.user, + description=description)[0].id + output = { + 'token': { + 'description': description, + 'id': token_id + } + } + + jsonout = flask.jsonify(output) + return jsonout diff --git a/pagure/lib/query.py b/pagure/lib/query.py index af39174..6749016 100644 --- a/pagure/lib/query.py +++ b/pagure/lib/query.py @@ -5205,8 +5205,8 @@ def get_obj_access(session, project_obj, obj): def search_token( - session, acls, user=None, token=None, active=False, expired=False -): + session, acls, user=None, token=None, active=False, expired=False, + description=None): """ Searches the API tokens corresponding to the criterias specified. :arg session: the session to use to connect to the database. @@ -5214,6 +5214,7 @@ def search_token( :arg user: restrict the API tokens to this given user :arg token: restrict the API tokens to this specified token (if it exists) + :arg description: restrict the API tokens to this given description """ query = ( session.query(model.Token) @@ -5232,6 +5233,9 @@ def search_token( model.User.user == user ) + if description: + query = query.filter(model.Token.description == description) + if active: query = query.filter( model.Token.expiration > datetime.datetime.utcnow() diff --git a/tests/test_pagure_flask_api_project.py b/tests/test_pagure_flask_api_project.py index 8502d68..39d3022 100644 --- a/tests/test_pagure_flask_api_project.py +++ b/tests/test_pagure_flask_api_project.py @@ -4096,6 +4096,179 @@ class PagureFlaskApiProjectOptionsTests(tests.Modeltests): before["settings"]["issues_default_to_private"] = True self.assertEqual(after, before) +class PagureFlaskApiProjectCreateAPITokenTests(tests.Modeltests): + """ Tests for the flask API of pagure for creating user project API token + """ + + maxDiff = None + + def setUp(self): + """ Set up the environnment, ran before every tests. """ + super(PagureFlaskApiProjectCreateAPITokenTests, self).setUp() + tests.create_projects(self.session) + tests.create_tokens(self.session, project_id=None) + tests.create_tokens_acl( + self.session, 'aaabbbcccddd', 'modify_project') + + def test_api_createapitoken_as_owner(self): + """ Test accessing api_project_createapitoken as owner. """ + + headers = {'Authorization': 'token aaabbbcccddd'} + project = pagure.lib.query._get_project(self.session, 'test') + tdescription = 'my new token' + + # Call the api with pingou user token and verify content + data = { + 'description': tdescription, + 'acl': 'pull_request_merge,pull_request_comment' + } + output = self.app.post('/api/0/test/createapitoken', + headers=headers, data=data) + self.assertEqual(output.status_code, 200) + data = json.loads(output.get_data(as_text=True)) + tid = pagure.lib.query.search_token( + self.session, None, description=tdescription)[0].id + self.assertEqual( + data, + {"token": { + "description": tdescription, + "id": tid + } + } + ) + # Create a second token but with faulty acl + # Call the api with pingou user token and error code + data = { + 'description': tdescription, + 'acl': 'foo,bar' + } + output = self.app.post('/api/0/test/createapitoken', + headers=headers, data=data) + self.assertEqual(output.status_code, 400) + + def test_api_createapitoken_as_admin(self): + """ Test accessing api_project_createapitoken as admin. """ + + project = pagure.lib.query._get_project(self.session, 'test') + + # Set the foo user as test project admin + pagure.lib.query.add_user_to_project( + self.session, project, + new_user='foo', + user='pingou', + access='admin' + ) + self.session.commit() + + # Create modify_project token for foo user + pagure.lib.query.add_token_to_user( + self.session, + project=None, + acls=['modify_project'], + username='foo') + mtoken = pagure.lib.query.search_token( + self.session, ['modify_project'], user='foo')[0] + + # Call the connector with foo user token and verify content + headers = {'Authorization': 'token %s' % mtoken.id} + tdescription = 'my new token' + + # Call the api with pingou user token and verify content + data = { + 'description': tdescription, + 'acl': 'pull_request_merge,pull_request_comment' + } + output = self.app.post('/api/0/test/createapitoken', + headers=headers, data=data) + self.assertEqual(output.status_code, 200) + data = json.loads(output.get_data(as_text=True)) + tid = pagure.lib.query.search_token( + self.session, None, user='foo', description=tdescription)[0].id + self.assertEqual( + data, + {"token": { + "description": tdescription, + "id": tid + } + } + ) + + def test_api_createapitoken_as_unauthorized(self): + """ Test accessing api_project_createapitoken as project admin + but with unauthorized token ACL. + """ + + project = pagure.lib.query._get_project(self.session, 'test') + + # Set the foo user as test project admin + pagure.lib.query.add_user_to_project( + self.session, project, + new_user='foo', + user='pingou', + access='admin' + ) + self.session.commit() + + # Create modify_project token for foo user + pagure.lib.query.add_token_to_user( + self.session, + project=None, + acls=['create_branch'], + username='foo') + mtoken = pagure.lib.query.search_token( + self.session, ['create_branch'], user='foo')[0] + + # Call the connector with foo user token and verify content + headers = {'Authorization': 'token %s' % mtoken.id} + tdescription = 'my new token' + + # Call the api with pingou user token and verify content + data = { + 'description': tdescription, + 'acl': 'pull_request_merge,pull_request_comment' + } + output = self.app.post('/api/0/test/createapitoken', + headers=headers, data=data) + self.assertEqual(output.status_code, 401) + + def test_api_createapitoken_as_unauthorized_2(self): + """ Test accessing api_project_createapitoken as project user + with unauthorized token ACL. + """ + + project = pagure.lib.query._get_project(self.session, 'test') + + # Set the foo user as test project admin + pagure.lib.query.add_user_to_project( + self.session, project, + new_user='foo', + user='pingou', + access='commit' + ) + self.session.commit() + + # Create modify_project token for foo user + pagure.lib.query.add_token_to_user( + self.session, + project=None, + acls=['modify_project'], + username='foo') + mtoken = pagure.lib.query.search_token( + self.session, ['modify_project'], user='foo')[0] + + # Call the connector with foo user token and verify content + headers = {'Authorization': 'token %s' % mtoken.id} + tdescription = 'my new token' + + # Call the api with pingou user token and verify content + data = { + 'description': tdescription, + 'acl': 'pull_request_merge,pull_request_comment' + } + output = self.app.post('/api/0/test/createapitoken', + headers=headers, data=data) + self.assertEqual(output.status_code, 401) + class PagureFlaskApiProjectConnectorTests(tests.Modeltests): """ Tests for the flask API of pagure for getting connector of a project From 41bac94853eb427c08b4461e5eb002f8428d8500 Mon Sep 17 00:00:00 2001 From: Fabien Boucher Date: Feb 11 2019 10:11:57 +0000 Subject: [PATCH 2/9] Attempt to fix wrong code stype --- diff --git a/pagure/api/project.py b/pagure/api/project.py index 83ab5b3..a035daf 100644 --- a/pagure/api/project.py +++ b/pagure/api/project.py @@ -2134,6 +2134,7 @@ def api_modify_project_options(repo, username=None, namespace=None): return flask.jsonify({"message": message, "status": "ok"}) + @API.route("//createapitoken", methods=["POST"]) @API.route("///createapitoken", methods=["POST"]) @API.route("/fork///createapitoken", methods=["POST"]) @@ -2200,7 +2201,6 @@ def api_project_create_api_token(repo, namespace=None, username=None): if flask.g.token.project and project != flask.g.token.project: raise pagure.exceptions.APIError(401, error_code=APIERROR.EINVALIDTOK) - authorized_users = [project.user.username] authorized_users.extend( [user.user for user in project.access_users['admin']]) @@ -2208,7 +2208,6 @@ def api_project_create_api_token(repo, namespace=None, username=None): raise pagure.exceptions.APIError( 401, error_code=APIERROR.ENOTHIGHENOUGH) - form = flask.request.form valid_form = True description = form.get('description') diff --git a/pagure/lib/query.py b/pagure/lib/query.py index 6749016..9e84be3 100644 --- a/pagure/lib/query.py +++ b/pagure/lib/query.py @@ -5206,7 +5206,7 @@ def get_obj_access(session, project_obj, obj): def search_token( session, acls, user=None, token=None, active=False, expired=False, - description=None): + description=None): """ Searches the API tokens corresponding to the criterias specified. :arg session: the session to use to connect to the database. From c2669c96a6e753dfbd7f8b4b7359d65ea2c3586e Mon Sep 17 00:00:00 2001 From: Fabien Boucher Date: Feb 11 2019 10:11:57 +0000 Subject: [PATCH 3/9] Propose a better API endpoint name repo/token/create Previous endpoint was poorly named. This patch proposes a better name. --- diff --git a/pagure/api/project.py b/pagure/api/project.py index a035daf..c33295f 100644 --- a/pagure/api/project.py +++ b/pagure/api/project.py @@ -2135,11 +2135,11 @@ def api_modify_project_options(repo, username=None, namespace=None): return flask.jsonify({"message": message, "status": "ok"}) -@API.route("//createapitoken", methods=["POST"]) -@API.route("///createapitoken", methods=["POST"]) -@API.route("/fork///createapitoken", methods=["POST"]) +@API.route("//token/create", methods=["POST"]) +@API.route("///token/create", methods=["POST"]) +@API.route("/fork///token/create", methods=["POST"]) @API.route( - "/fork////createapitoken", methods=["POST"] + "/fork////token/create", methods=["POST"] ) @api_login_required(acls=["modify_project"]) @api_method @@ -2153,13 +2153,13 @@ def api_project_create_api_token(repo, namespace=None, username=None): :: - POST /api/0//createapitoken - POST /api/0///createapitoken + POST /api/0//token/create + POST /api/0///token/create :: - POST /api/0/fork///createapitoken - POST /api/0/fork////createapitoken + POST /api/0/fork///token/create + POST /api/0/fork////token/create Input diff --git a/tests/test_pagure_flask_api_project.py b/tests/test_pagure_flask_api_project.py index 39d3022..560e82c 100644 --- a/tests/test_pagure_flask_api_project.py +++ b/tests/test_pagure_flask_api_project.py @@ -4122,7 +4122,7 @@ class PagureFlaskApiProjectCreateAPITokenTests(tests.Modeltests): 'description': tdescription, 'acl': 'pull_request_merge,pull_request_comment' } - output = self.app.post('/api/0/test/createapitoken', + output = self.app.post('/api/0/test/token/create', headers=headers, data=data) self.assertEqual(output.status_code, 200) data = json.loads(output.get_data(as_text=True)) @@ -4142,7 +4142,7 @@ class PagureFlaskApiProjectCreateAPITokenTests(tests.Modeltests): 'description': tdescription, 'acl': 'foo,bar' } - output = self.app.post('/api/0/test/createapitoken', + output = self.app.post('/api/0/test/token/create', headers=headers, data=data) self.assertEqual(output.status_code, 400) @@ -4178,7 +4178,7 @@ class PagureFlaskApiProjectCreateAPITokenTests(tests.Modeltests): 'description': tdescription, 'acl': 'pull_request_merge,pull_request_comment' } - output = self.app.post('/api/0/test/createapitoken', + output = self.app.post('/api/0/test/token/create', headers=headers, data=data) self.assertEqual(output.status_code, 200) data = json.loads(output.get_data(as_text=True)) @@ -4227,7 +4227,7 @@ class PagureFlaskApiProjectCreateAPITokenTests(tests.Modeltests): 'description': tdescription, 'acl': 'pull_request_merge,pull_request_comment' } - output = self.app.post('/api/0/test/createapitoken', + output = self.app.post('/api/0/test/token/create', headers=headers, data=data) self.assertEqual(output.status_code, 401) @@ -4265,7 +4265,7 @@ class PagureFlaskApiProjectCreateAPITokenTests(tests.Modeltests): 'description': tdescription, 'acl': 'pull_request_merge,pull_request_comment' } - output = self.app.post('/api/0/test/createapitoken', + output = self.app.post('/api/0/test/token/create', headers=headers, data=data) self.assertEqual(output.status_code, 401) From 53b7929689d4ac55124aedc0fded10e94dfb53a1 Mon Sep 17 00:00:00 2001 From: Fabien Boucher Date: Feb 11 2019 10:11:57 +0000 Subject: [PATCH 4/9] Use wtforms to validate a new token in the projects api --- diff --git a/pagure/api/project.py b/pagure/api/project.py index c33295f..622a7f5 100644 --- a/pagure/api/project.py +++ b/pagure/api/project.py @@ -2168,12 +2168,11 @@ def api_project_create_api_token(repo, namespace=None, username=None): +------------------+---------+---------------+---------------------------+ | Key | Type | Optionality | Description | +==================+=========+===============+===========================+ - | ``desc`` | String | Mandatory | A string to specify the | + | ``description`` | String | optional | A string to specify the | | | | | description of the token | | | | | | +------------------+---------+---------------+---------------------------+ - | ``acl`` | String | Mandatory | The ACL as a comma | - | | | | string | + | ``acls`` | List | Mandatory | The ACLs | | | | | | +------------------+---------+---------------+---------------------------+ @@ -2208,26 +2207,21 @@ def api_project_create_api_token(repo, namespace=None, username=None): raise pagure.exceptions.APIError( 401, error_code=APIERROR.ENOTHIGHENOUGH) - form = flask.request.form - valid_form = True - description = form.get('description') - acl = form.get('acl') - if not isinstance(description, str) or not isinstance(acl, str): - valid_form = False - acl_list = acl.split(',') - for ac in acl_list: - if ac not in pagure_config.get("ACLS", []): - valid_form = False - break - if not valid_form: + authorized_acls = pagure_config.get("ACLS", {}).keys() + form = pagure.forms.NewTokenForm( + csrf_enabled=False, sacls=authorized_acls) + if form.validate_on_submit(): + acls = form.acls.data + description = form.description.data + else: raise pagure.exceptions.APIError( - 400, error_code=APIERROR.EINVALIDREQ) + 400, error_code=APIERROR.EINVALIDREQ, errors=form.errors) pagure.lib.query.add_token_to_user( - flask.g.session, project, acl.split(','), flask.g.fas_user.user, + flask.g.session, project, acls, flask.g.fas_user.user, description) token_id = pagure.lib.query.search_token( - flask.g.session, None, user=flask.g.fas_user.user, + flask.g.session, acls=None, user=flask.g.fas_user.user, description=description)[0].id output = { 'token': { diff --git a/pagure/forms.py b/pagure/forms.py index d2ba507..a063c9c 100644 --- a/pagure/forms.py +++ b/pagure/forms.py @@ -407,7 +407,7 @@ class MilestoneForm(PagureForm): class NewTokenForm(PagureForm): - """ Form to add/change the status of an issue. """ + """ Form to add a new token. """ description = wtforms.StringField( "description", [wtforms.validators.Optional()] @@ -426,6 +426,9 @@ class NewTokenForm(PagureForm): self.acls.choices = [ (acl.name, acl.name) for acl in kwargs["acls"] ] + if "sacls" in kwargs: + self.acls.choices = [ + (acl, acl) for acl in kwargs['sacls']] class UpdateIssueForm(PagureForm): diff --git a/tests/test_pagure_flask_api_project.py b/tests/test_pagure_flask_api_project.py index 560e82c..97ab8ff 100644 --- a/tests/test_pagure_flask_api_project.py +++ b/tests/test_pagure_flask_api_project.py @@ -4111,7 +4111,7 @@ class PagureFlaskApiProjectCreateAPITokenTests(tests.Modeltests): self.session, 'aaabbbcccddd', 'modify_project') def test_api_createapitoken_as_owner(self): - """ Test accessing api_project_createapitoken as owner. """ + """ Test accessing api_project_create_token as owner. """ headers = {'Authorization': 'token aaabbbcccddd'} project = pagure.lib.query._get_project(self.session, 'test') @@ -4120,7 +4120,7 @@ class PagureFlaskApiProjectCreateAPITokenTests(tests.Modeltests): # Call the api with pingou user token and verify content data = { 'description': tdescription, - 'acl': 'pull_request_merge,pull_request_comment' + 'acls': ['pull_request_merge', 'pull_request_comment'] } output = self.app.post('/api/0/test/token/create', headers=headers, data=data) @@ -4140,14 +4140,14 @@ class PagureFlaskApiProjectCreateAPITokenTests(tests.Modeltests): # Call the api with pingou user token and error code data = { 'description': tdescription, - 'acl': 'foo,bar' + 'acl': ['foo', 'bar'] } output = self.app.post('/api/0/test/token/create', headers=headers, data=data) self.assertEqual(output.status_code, 400) def test_api_createapitoken_as_admin(self): - """ Test accessing api_project_createapitoken as admin. """ + """ Test accessing api_project_create_token as admin. """ project = pagure.lib.query._get_project(self.session, 'test') @@ -4176,7 +4176,7 @@ class PagureFlaskApiProjectCreateAPITokenTests(tests.Modeltests): # Call the api with pingou user token and verify content data = { 'description': tdescription, - 'acl': 'pull_request_merge,pull_request_comment' + 'acls': ['pull_request_merge', 'pull_request_comment'] } output = self.app.post('/api/0/test/token/create', headers=headers, data=data) @@ -4194,7 +4194,7 @@ class PagureFlaskApiProjectCreateAPITokenTests(tests.Modeltests): ) def test_api_createapitoken_as_unauthorized(self): - """ Test accessing api_project_createapitoken as project admin + """ Test accessing api_project_create_token as project admin but with unauthorized token ACL. """ @@ -4225,14 +4225,14 @@ class PagureFlaskApiProjectCreateAPITokenTests(tests.Modeltests): # Call the api with pingou user token and verify content data = { 'description': tdescription, - 'acl': 'pull_request_merge,pull_request_comment' + 'acls': ['pull_request_merge', 'pull_request_comment'] } output = self.app.post('/api/0/test/token/create', headers=headers, data=data) self.assertEqual(output.status_code, 401) def test_api_createapitoken_as_unauthorized_2(self): - """ Test accessing api_project_createapitoken as project user + """ Test accessing api_project_create_token as project user with unauthorized token ACL. """ @@ -4263,7 +4263,7 @@ class PagureFlaskApiProjectCreateAPITokenTests(tests.Modeltests): # Call the api with pingou user token and verify content data = { 'description': tdescription, - 'acl': 'pull_request_merge,pull_request_comment' + 'acls': ['pull_request_merge', 'pull_request_comment'] } output = self.app.post('/api/0/test/token/create', headers=headers, data=data) From 579887ce790cb441adf379b5181cdc6aad408b22 Mon Sep 17 00:00:00 2001 From: Fabien Boucher Date: Feb 11 2019 10:11:57 +0000 Subject: [PATCH 5/9] Improve add_token_to_user to return the token --- diff --git a/pagure/api/project.py b/pagure/api/project.py index 622a7f5..93a0bc4 100644 --- a/pagure/api/project.py +++ b/pagure/api/project.py @@ -2207,7 +2207,7 @@ def api_project_create_api_token(repo, namespace=None, username=None): raise pagure.exceptions.APIError( 401, error_code=APIERROR.ENOTHIGHENOUGH) - authorized_acls = pagure_config.get("ACLS", {}).keys() + authorized_acls = pagure_config.get("USER_ACLS", []) form = pagure.forms.NewTokenForm( csrf_enabled=False, sacls=authorized_acls) if form.validate_on_submit(): @@ -2217,16 +2217,13 @@ def api_project_create_api_token(repo, namespace=None, username=None): raise pagure.exceptions.APIError( 400, error_code=APIERROR.EINVALIDREQ, errors=form.errors) - pagure.lib.query.add_token_to_user( + token = pagure.lib.query.add_token_to_user( flask.g.session, project, acls, flask.g.fas_user.user, description) - token_id = pagure.lib.query.search_token( - flask.g.session, acls=None, user=flask.g.fas_user.user, - description=description)[0].id output = { 'token': { - 'description': description, - 'id': token_id + 'description': token.description, + 'id': token.id } } diff --git a/pagure/lib/query.py b/pagure/lib/query.py index 9e84be3..d2ea05e 100644 --- a/pagure/lib/query.py +++ b/pagure/lib/query.py @@ -4176,7 +4176,7 @@ def add_token_to_user(session, project, acls, username, description=None): session.commit() - return "Token created" + return token def _convert_markdown(md_processor, text): diff --git a/tests/test_pagure_flask_api_project.py b/tests/test_pagure_flask_api_project.py index 97ab8ff..d4fd8fb 100644 --- a/tests/test_pagure_flask_api_project.py +++ b/tests/test_pagure_flask_api_project.py @@ -4161,16 +4161,14 @@ class PagureFlaskApiProjectCreateAPITokenTests(tests.Modeltests): self.session.commit() # Create modify_project token for foo user - pagure.lib.query.add_token_to_user( + token = pagure.lib.query.add_token_to_user( self.session, project=None, acls=['modify_project'], username='foo') - mtoken = pagure.lib.query.search_token( - self.session, ['modify_project'], user='foo')[0] # Call the connector with foo user token and verify content - headers = {'Authorization': 'token %s' % mtoken.id} + headers = {'Authorization': 'token %s' % token.id} tdescription = 'my new token' # Call the api with pingou user token and verify content From 696f19ee5423c8a01b8d20da467276bcabaf75c4 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Feb 11 2019 11:22:01 +0000 Subject: [PATCH 6/9] Fix the tests We now return the created API token instead of the message to show to the users. So inform the users about the success of the operation in the controller directly. This fixes the tests as the Token object was not json serializable while the info string is. Signed-off-by: Pierre-Yves Chibon --- diff --git a/pagure/ui/app.py b/pagure/ui/app.py index 4b2818c..aa5a5e1 100644 --- a/pagure/ui/app.py +++ b/pagure/ui/app.py @@ -1489,7 +1489,7 @@ def add_api_user_token(): if form.validate_on_submit(): try: - msg = pagure.lib.query.add_token_to_user( + pagure.lib.query.add_token_to_user( flask.g.session, project=None, description=form.description.data.strip() or None, @@ -1497,7 +1497,7 @@ def add_api_user_token(): username=user.username, ) flask.g.session.commit() - flask.flash(msg) + flask.flash("Token created") return flask.redirect( flask.url_for("ui_ns.user_settings") + "#nav-api-tab" ) diff --git a/pagure/ui/repo.py b/pagure/ui/repo.py index 3b4736b..deeb315 100644 --- a/pagure/ui/repo.py +++ b/pagure/ui/repo.py @@ -2255,7 +2255,7 @@ def add_token(repo, username=None, namespace=None): if form.validate_on_submit(): try: - msg = pagure.lib.query.add_token_to_user( + pagure.lib.query.add_token_to_user( flask.g.session, repo, description=form.description.data.strip() or None, @@ -2263,7 +2263,7 @@ def add_token(repo, username=None, namespace=None): username=flask.g.fas_user.username, ) flask.g.session.commit() - flask.flash(msg) + flask.flash("Token created") return flask.redirect( flask.url_for( "ui_ns.view_settings", @@ -2324,7 +2324,7 @@ def renew_api_token(repo, token_id, username=None, namespace=None): if form.validate_on_submit(): acls = [acl.name for acl in token.acls] try: - msg = pagure.lib.query.add_token_to_user( + pagure.lib.query.add_token_to_user( flask.g.session, repo, description=token.description or None, @@ -2332,7 +2332,7 @@ def renew_api_token(repo, token_id, username=None, namespace=None): username=flask.g.fas_user.username, ) flask.g.session.commit() - flask.flash(msg) + flask.flash("Token created") return flask.redirect( flask.url_for( "ui_ns.view_settings", From 3b2728c22ff75d38410f22410bd84d3779100c28 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Feb 11 2019 11:22:08 +0000 Subject: [PATCH 7/9] Black8 fixes Signed-off-by: Pierre-Yves Chibon --- diff --git a/pagure/api/project.py b/pagure/api/project.py index 93a0bc4..83da8ac 100644 --- a/pagure/api/project.py +++ b/pagure/api/project.py @@ -2202,30 +2202,27 @@ def api_project_create_api_token(repo, namespace=None, username=None): authorized_users = [project.user.username] authorized_users.extend( - [user.user for user in project.access_users['admin']]) + [user.user for user in project.access_users["admin"]] + ) if flask.g.fas_user.user not in authorized_users: raise pagure.exceptions.APIError( - 401, error_code=APIERROR.ENOTHIGHENOUGH) + 401, error_code=APIERROR.ENOTHIGHENOUGH + ) authorized_acls = pagure_config.get("USER_ACLS", []) - form = pagure.forms.NewTokenForm( - csrf_enabled=False, sacls=authorized_acls) + form = pagure.forms.NewTokenForm(csrf_enabled=False, sacls=authorized_acls) if form.validate_on_submit(): acls = form.acls.data description = form.description.data else: raise pagure.exceptions.APIError( - 400, error_code=APIERROR.EINVALIDREQ, errors=form.errors) + 400, error_code=APIERROR.EINVALIDREQ, errors=form.errors + ) token = pagure.lib.query.add_token_to_user( - flask.g.session, project, acls, flask.g.fas_user.user, - description) - output = { - 'token': { - 'description': token.description, - 'id': token.id - } - } + flask.g.session, project, acls, flask.g.fas_user.user, description + ) + output = {"token": {"description": token.description, "id": token.id}} jsonout = flask.jsonify(output) return jsonout diff --git a/pagure/forms.py b/pagure/forms.py index a063c9c..fcc6ac1 100644 --- a/pagure/forms.py +++ b/pagure/forms.py @@ -427,8 +427,7 @@ class NewTokenForm(PagureForm): (acl.name, acl.name) for acl in kwargs["acls"] ] if "sacls" in kwargs: - self.acls.choices = [ - (acl, acl) for acl in kwargs['sacls']] + self.acls.choices = [(acl, acl) for acl in kwargs["sacls"]] class UpdateIssueForm(PagureForm): diff --git a/pagure/lib/query.py b/pagure/lib/query.py index d2ea05e..325fa61 100644 --- a/pagure/lib/query.py +++ b/pagure/lib/query.py @@ -5205,8 +5205,14 @@ def get_obj_access(session, project_obj, obj): def search_token( - session, acls, user=None, token=None, active=False, expired=False, - description=None): + session, + acls, + user=None, + token=None, + active=False, + expired=False, + description=None, +): """ Searches the API tokens corresponding to the criterias specified. :arg session: the session to use to connect to the database. From 1a6b69737fbe342fea65a0ffc2e6d936b41eabb1 Mon Sep 17 00:00:00 2001 From: Fabien Boucher Date: Feb 11 2019 11:28:06 +0000 Subject: [PATCH 8/9] Align new token API endpoint with UI endpoint This patch changes endpoint path from /token/create to /token/new. --- diff --git a/pagure/api/project.py b/pagure/api/project.py index 83da8ac..20c6e8a 100644 --- a/pagure/api/project.py +++ b/pagure/api/project.py @@ -2135,11 +2135,11 @@ def api_modify_project_options(repo, username=None, namespace=None): return flask.jsonify({"message": message, "status": "ok"}) -@API.route("//token/create", methods=["POST"]) -@API.route("///token/create", methods=["POST"]) -@API.route("/fork///token/create", methods=["POST"]) +@API.route("//token/new", methods=["POST"]) +@API.route("///token/new", methods=["POST"]) +@API.route("/fork///token/new", methods=["POST"]) @API.route( - "/fork////token/create", methods=["POST"] + "/fork////token/new", methods=["POST"] ) @api_login_required(acls=["modify_project"]) @api_method @@ -2153,13 +2153,13 @@ def api_project_create_api_token(repo, namespace=None, username=None): :: - POST /api/0//token/create - POST /api/0///token/create + POST /api/0//token/new + POST /api/0///token/new :: - POST /api/0/fork///token/create - POST /api/0/fork////token/create + POST /api/0/fork///token/new + POST /api/0/fork////token/new Input diff --git a/tests/test_pagure_flask_api_project.py b/tests/test_pagure_flask_api_project.py index d4fd8fb..1175abb 100644 --- a/tests/test_pagure_flask_api_project.py +++ b/tests/test_pagure_flask_api_project.py @@ -4122,7 +4122,7 @@ class PagureFlaskApiProjectCreateAPITokenTests(tests.Modeltests): 'description': tdescription, 'acls': ['pull_request_merge', 'pull_request_comment'] } - output = self.app.post('/api/0/test/token/create', + output = self.app.post('/api/0/test/token/new', headers=headers, data=data) self.assertEqual(output.status_code, 200) data = json.loads(output.get_data(as_text=True)) @@ -4142,7 +4142,7 @@ class PagureFlaskApiProjectCreateAPITokenTests(tests.Modeltests): 'description': tdescription, 'acl': ['foo', 'bar'] } - output = self.app.post('/api/0/test/token/create', + output = self.app.post('/api/0/test/token/new', headers=headers, data=data) self.assertEqual(output.status_code, 400) @@ -4176,7 +4176,7 @@ class PagureFlaskApiProjectCreateAPITokenTests(tests.Modeltests): 'description': tdescription, 'acls': ['pull_request_merge', 'pull_request_comment'] } - output = self.app.post('/api/0/test/token/create', + output = self.app.post('/api/0/test/token/new', headers=headers, data=data) self.assertEqual(output.status_code, 200) data = json.loads(output.get_data(as_text=True)) @@ -4225,7 +4225,7 @@ class PagureFlaskApiProjectCreateAPITokenTests(tests.Modeltests): 'description': tdescription, 'acls': ['pull_request_merge', 'pull_request_comment'] } - output = self.app.post('/api/0/test/token/create', + output = self.app.post('/api/0/test/token/new', headers=headers, data=data) self.assertEqual(output.status_code, 401) @@ -4263,7 +4263,7 @@ class PagureFlaskApiProjectCreateAPITokenTests(tests.Modeltests): 'description': tdescription, 'acls': ['pull_request_merge', 'pull_request_comment'] } - output = self.app.post('/api/0/test/token/create', + output = self.app.post('/api/0/test/token/new', headers=headers, data=data) self.assertEqual(output.status_code, 401) From 032e3d2174a73cd0e7892573a93dc342eb8a5722 Mon Sep 17 00:00:00 2001 From: Fabien Boucher Date: Feb 11 2019 12:49:44 +0000 Subject: [PATCH 9/9] Fix black compliance --- diff --git a/pagure/api/project.py b/pagure/api/project.py index 20c6e8a..e947a30 100644 --- a/pagure/api/project.py +++ b/pagure/api/project.py @@ -2138,9 +2138,7 @@ def api_modify_project_options(repo, username=None, namespace=None): @API.route("//token/new", methods=["POST"]) @API.route("///token/new", methods=["POST"]) @API.route("/fork///token/new", methods=["POST"]) -@API.route( - "/fork////token/new", methods=["POST"] -) +@API.route("/fork////token/new", methods=["POST"]) @api_login_required(acls=["modify_project"]) @api_method def api_project_create_api_token(repo, namespace=None, username=None):