From ed5d68700f58d2cd5f0ae10b8cc2cbcde9261b43 Mon Sep 17 00:00:00 2001 From: Mattia Verga Date: Jan 21 2024 23:51:13 +0000 Subject: Add verify_token API endpoint Signed-off-by: Mattia Verga --- diff --git a/pagure/api/__init__.py b/pagure/api/__init__.py index 14486f0..c711be6 100644 --- a/pagure/api/__init__.py +++ b/pagure/api/__init__.py @@ -557,6 +557,7 @@ def api(): project.api_project_block_user, project.api_get_project_webhook_token, project.api_project_create_api_token, + project.api_project_verify_api_token, project.api_commit_info, project.api_view_file, project.delete_project, diff --git a/pagure/api/project.py b/pagure/api/project.py index 52bf413..785ebb1 100644 --- a/pagure/api/project.py +++ b/pagure/api/project.py @@ -3214,6 +3214,51 @@ def api_project_create_api_token(repo, namespace=None, username=None): return jsonout +@API.route("//token/verify", methods=["POST"]) +@API.route("///token/verify", methods=["POST"]) +@API.route("/fork///token/verify", methods=["POST"]) +@API.route( + "/fork////token/verify", methods=["POST"] +) +@api_method +@api_login_required(acls=["modify_project"]) +def api_project_verify_api_token(repo, namespace=None, username=None): + """ + Verify API project Token + ------------------------ + Verify validity of a token API for the specified project + + It does not verify token scope, but can be used to check if the + token exists or is expired. + + :: + + POST /api/0//token/verify + POST /api/0///token/verify + + :: + + POST /api/0/fork///token/verify + POST /api/0/fork////token/verify + + + Sample response + ^^^^^^^^^^^^^^^ + + :: + + {"message": "Token is valid"} + + """ + output = {"message": "Token is valid"} + + project = _get_repo(repo, username, namespace) + _check_token(project, project_token=False) + + jsonout = flask.jsonify(output) + return jsonout + + @API.route("//blockuser", methods=["POST"]) @API.route("///blockuser", methods=["POST"]) @API.route("/fork///blockuser", methods=["POST"]) diff --git a/pagure/api/utils.py b/pagure/api/utils.py index 2df505a..da590ee 100644 --- a/pagure/api/utils.py +++ b/pagure/api/utils.py @@ -49,15 +49,14 @@ def _check_token(repo, project_token=True): otherwise any token can be used :raises pagure.exceptions.APIError: when token is not valid for repo """ - if api_authenticated(): - # if there is a project associated with the token, check it - # if there is no project associated, check if it is required - if ( + if ( + not api_authenticated() + or ( flask.g.token.project is not None and repo != flask.g.token.project - ) or (flask.g.token.project is None and project_token): - raise pagure.exceptions.APIError( - 401, error_code=APIERROR.EINVALIDTOK - ) + ) + or (flask.g.token.project is None and project_token) + ): + raise pagure.exceptions.APIError(401, error_code=APIERROR.EINVALIDTOK) def _get_issue(repo, issueid, issueuid=None): diff --git a/tests/test_pagure_flask_api_project.py b/tests/test_pagure_flask_api_project.py index 2227dc6..4664941 100644 --- a/tests/test_pagure_flask_api_project.py +++ b/tests/test_pagure_flask_api_project.py @@ -4722,6 +4722,65 @@ class PagureFlaskApiProjectCreateAPITokenTests(tests.Modeltests): self.assertEqual(output.status_code, 401) +class PagureFlaskApiProjectVerifyAPITokenTests(tests.Modeltests): + """Tests for the flask API of pagure for verifying project API token validity""" + + maxDiff = None + + def setUp(self): + """Set up the environnment, ran before every tests.""" + super(PagureFlaskApiProjectVerifyAPITokenTests, 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_verifyapitoken_valid(self): + """Test accessing api_project_verify_api_token with valid token.""" + + headers = {"Authorization": "token aaabbbcccddd"} + + output = self.app.post("/api/0/test/token/verify", headers=headers) + self.assertEqual(output.status_code, 200) + data = json.loads(output.get_data(as_text=True)) + self.assertEqual(data, {"message": "Token is valid"}) + + def test_api_verifyapitoken_not_valid(self): + """Test accessing api_project_verify_api_token with invalid token.""" + + headers = {"Authorization": "token dddcccbbbaaa"} + + output = self.app.post("/api/0/test/token/verify", headers=headers) + self.assertEqual(output.status_code, 401) + data = json.loads(output.get_data(as_text=True)) + self.assertDictEqual( + data, + { + "error": "Invalid or expired token. Please visit " + "http://localhost.localdomain/settings#nav-api-tab to get or renew " + "your API token.", + "error_code": "EINVALIDTOK", + "errors": "Invalid token", + }, + ) + + def test_api_verifyapitoken_no_headers(self): + """Test accessing api_project_verify_api_token without passing headers.""" + + output = self.app.post("/api/0/test/token/verify") + self.assertEqual(output.status_code, 401) + data = json.loads(output.get_data(as_text=True)) + self.assertDictEqual( + data, + { + "error": "Invalid or expired token. Please visit " + "http://localhost.localdomain/settings#nav-api-tab to get or renew " + "your API token.", + "error_code": "EINVALIDTOK", + "errors": "Invalid token", + }, + ) + + class PagureFlaskApiProjectConnectorTests(tests.Modeltests): """Tests for the flask API of pagure for getting connector of a project"""