From 31c137a1441b2ff0bff575ee4e3dcce094b32e3a Mon Sep 17 00:00:00 2001 From: Mmequignon Date: Wed, 28 Feb 2024 13:11:48 +0100 Subject: [PATCH 01/12] Add fastapi_auth_api_key --- fastapi_auth_api_key/README.rst | 0 fastapi_auth_api_key/__init__.py | 1 + fastapi_auth_api_key/__manifest__.py | 20 + fastapi_auth_api_key/dependencies.py | 60 +++ fastapi_auth_api_key/models/__init__.py | 1 + .../models/fastapi_endpoint.py | 10 + fastapi_auth_api_key/readme/CONTRIBUTORS.rst | 1 + fastapi_auth_api_key/readme/DESCRIPTION.rst | 1 + fastapi_auth_api_key/readme/USAGE.rst | 33 ++ .../static/description/index.html | 369 ++++++++++++++++++ fastapi_auth_api_key/tests/__init__.py | 1 + .../test_fastapi_api_key_dependencies.py | 88 +++++ .../views/fastapi_endpoint.xml | 17 + 13 files changed, 602 insertions(+) create mode 100644 fastapi_auth_api_key/README.rst create mode 100644 fastapi_auth_api_key/__init__.py create mode 100644 fastapi_auth_api_key/__manifest__.py create mode 100644 fastapi_auth_api_key/dependencies.py create mode 100644 fastapi_auth_api_key/models/__init__.py create mode 100644 fastapi_auth_api_key/models/fastapi_endpoint.py create mode 100644 fastapi_auth_api_key/readme/CONTRIBUTORS.rst create mode 100644 fastapi_auth_api_key/readme/DESCRIPTION.rst create mode 100644 fastapi_auth_api_key/readme/USAGE.rst create mode 100644 fastapi_auth_api_key/static/description/index.html create mode 100644 fastapi_auth_api_key/tests/__init__.py create mode 100644 fastapi_auth_api_key/tests/test_fastapi_api_key_dependencies.py create mode 100644 fastapi_auth_api_key/views/fastapi_endpoint.xml diff --git a/fastapi_auth_api_key/README.rst b/fastapi_auth_api_key/README.rst new file mode 100644 index 000000000..e69de29bb diff --git a/fastapi_auth_api_key/__init__.py b/fastapi_auth_api_key/__init__.py new file mode 100644 index 000000000..0650744f6 --- /dev/null +++ b/fastapi_auth_api_key/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/fastapi_auth_api_key/__manifest__.py b/fastapi_auth_api_key/__manifest__.py new file mode 100644 index 000000000..1735c59be --- /dev/null +++ b/fastapi_auth_api_key/__manifest__.py @@ -0,0 +1,20 @@ +# Copyright 2024 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) + +{ + "name": "Fastapi Auth Api Key", + "version": "16.0.1.0.0", + "category": "Others", + "website": "https://github.com/OCA/rest-framework", + "author": "Camptocamp, Odoo Community Association (OCA)", + "maintainers": ["mmequignon"], + "license": "AGPL-3", + "installable": True, + "depends": [ + "fastapi", + "auth_api_key_group", + ], + "data": [ + "views/fastapi_endpoint.xml", + ], +} diff --git a/fastapi_auth_api_key/dependencies.py b/fastapi_auth_api_key/dependencies.py new file mode 100644 index 000000000..3b71e6d58 --- /dev/null +++ b/fastapi_auth_api_key/dependencies.py @@ -0,0 +1,60 @@ +# Copyright 2024 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) + +from typing_extensions import Annotated + +from odoo import SUPERUSER_ID +from odoo.api import Environment +from odoo.exceptions import ValidationError + +from odoo.addons.auth_api_key.models.auth_api_key import AuthApiKey +from odoo.addons.base.models.res_partner import Partner +from odoo.addons.fastapi.dependencies import fastapi_endpoint, odoo_env +from odoo.addons.fastapi.models.fastapi_endpoint import FastapiEndpoint + +from fastapi import Depends, status +from fastapi.exceptions import HTTPException +from fastapi.security import APIKeyHeader + + +def authenticated_auth_api_key( + key: Annotated[str, Depends(APIKeyHeader(name="HTTP-API-KEY"))], + env: Annotated[Environment, Depends(odoo_env)], + endpoint: Annotated[FastapiEndpoint, Depends(fastapi_endpoint)], +) -> AuthApiKey: + if not key: + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail="No HTTP-API-KEY provided", + headers={"WWW-Authenticate": "HTTP-API-KEY"}, + ) + admin_env = Environment(env.cr, SUPERUSER_ID, {}) + try: + auth_api_key = admin_env["auth.api.key"]._retrieve_api_key(key) + except ValidationError as error: + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail=error.name, + headers={"WWW-Authenticate": "HTTP-API-KEY"}, + ) from error + # Ensure the api key is authorized for the current endpoint. + if auth_api_key not in endpoint.sudo().auth_api_key_group_id.auth_api_key_ids: + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail="Unauthorized", + headers={"WWW-Authenticate": "HTTP-API-KEY"}, + ) + return auth_api_key + + +def authenticated_partner_by_api_key( + auth_api_key: Annotated[AuthApiKey, Depends(authenticated_auth_api_key)] +) -> Partner: + return auth_api_key.user_id.partner_id + + +def authenticated_env_by_auth_api_key( + auth_api_key: Annotated[AuthApiKey, Depends(authenticated_auth_api_key)] +) -> Environment: + # set api key id in context + return auth_api_key.with_user(auth_api_key.user_id).env diff --git a/fastapi_auth_api_key/models/__init__.py b/fastapi_auth_api_key/models/__init__.py new file mode 100644 index 000000000..b825fab92 --- /dev/null +++ b/fastapi_auth_api_key/models/__init__.py @@ -0,0 +1 @@ +from . import fastapi_endpoint diff --git a/fastapi_auth_api_key/models/fastapi_endpoint.py b/fastapi_auth_api_key/models/fastapi_endpoint.py new file mode 100644 index 000000000..8da7ff66d --- /dev/null +++ b/fastapi_auth_api_key/models/fastapi_endpoint.py @@ -0,0 +1,10 @@ +# Copyright 2024 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) + +from odoo import fields, models + + +class FastapiEndpoint(models.Model): + _inherit = "fastapi.endpoint" + + auth_api_key_group_id = fields.Many2one("auth.api.key.group") diff --git a/fastapi_auth_api_key/readme/CONTRIBUTORS.rst b/fastapi_auth_api_key/readme/CONTRIBUTORS.rst new file mode 100644 index 000000000..bca4ee0ca --- /dev/null +++ b/fastapi_auth_api_key/readme/CONTRIBUTORS.rst @@ -0,0 +1 @@ +* Matthieu Méquignon diff --git a/fastapi_auth_api_key/readme/DESCRIPTION.rst b/fastapi_auth_api_key/readme/DESCRIPTION.rst new file mode 100644 index 000000000..22e772df2 --- /dev/null +++ b/fastapi_auth_api_key/readme/DESCRIPTION.rst @@ -0,0 +1 @@ +Provides `FastAPI` dependencies for Api Key authentication. diff --git a/fastapi_auth_api_key/readme/USAGE.rst b/fastapi_auth_api_key/readme/USAGE.rst new file mode 100644 index 000000000..356cb02d2 --- /dev/null +++ b/fastapi_auth_api_key/readme/USAGE.rst @@ -0,0 +1,33 @@ +Getting an odoo environment +=========================== + +If you need to get an odoo env based on the provided api key, you can use `authenticated_env_by_auth_api_key`. + +.. code-block:: python + + @router.get("/example_with_authenticated_env") + def example_with_authenticated_env( + env: Annotated[Environment, Depends(authenticated_env_by_auth_api_key)], + ) -> None: + # env.user is the user attached to the provided key + pass + +Getting the authenticated partner +================================= + +If want to get the partned related to the the provided api key, you can use `authenticated_partner_by_api_key` + +.. code-block:: python + + @router.get("/example_with_authenticated_partner") + def example_with_authenticated_partner( + partner: Annotated[Partner, Depends(authenticated_partner_by_api_key)], + ) -> None: + # partner is the partner related to the provided key key.user_id.partner_id + pass + +Configuration +============= + +For this to work, the api key must be defined on the `Endpoint`. +A new field `auth_api_key_group_id` has been added to the `Endpoint` model. diff --git a/fastapi_auth_api_key/static/description/index.html b/fastapi_auth_api_key/static/description/index.html new file mode 100644 index 000000000..ec3643de8 --- /dev/null +++ b/fastapi_auth_api_key/static/description/index.html @@ -0,0 +1,369 @@ + + + + + + +README.rst + + + +
+ + + +
+ + diff --git a/fastapi_auth_api_key/tests/__init__.py b/fastapi_auth_api_key/tests/__init__.py new file mode 100644 index 000000000..da7258cc3 --- /dev/null +++ b/fastapi_auth_api_key/tests/__init__.py @@ -0,0 +1 @@ +from . import test_fastapi_api_key_dependencies diff --git a/fastapi_auth_api_key/tests/test_fastapi_api_key_dependencies.py b/fastapi_auth_api_key/tests/test_fastapi_api_key_dependencies.py new file mode 100644 index 000000000..d746e1ccc --- /dev/null +++ b/fastapi_auth_api_key/tests/test_fastapi_api_key_dependencies.py @@ -0,0 +1,88 @@ +from odoo.tests import tagged +from odoo.tests.common import TransactionCase + +from fastapi.exceptions import HTTPException + +from ..dependencies import ( + authenticated_auth_api_key, + authenticated_env_by_auth_api_key, + authenticated_partner_by_api_key, +) + + +@tagged("-at_install", "post_install") +class TestFastapiAuthApiKey(TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True)) + # Is it valid? We need an env without superpowers + demo_user = cls.env.ref("base.partner_demo") + cls.demo_env = demo_user.with_user(demo_user).env + cls.setUpClassApiKey() + + @classmethod + def setUpClassApiKey(cls): + user_model = cls.env["res.users"].with_context(no_reset_password=True) + cls.authorized_user = user_model.create( + { + "name": "John Authorized", + "login": "johnauth", + } + ) + cls.unauthorized_user = user_model.create( + { + "name": "Bob Unauthorized", + "login": "bobunauth", + } + ) + api_key_model = cls.env["auth.api.key"] + cls.authorized_api_key = api_key_model.create( + { + "user_id": cls.authorized_user.id, + "name": "Authorized api key", + "key": "authorized_key", + } + ) + cls.unauthorized_api_key = api_key_model.create( + { + "user_id": cls.unauthorized_user.id, + "name": "Unauthorized api key", + "key": "unauthorized_key", + } + ) + api_key_group_model = cls.env["auth.api.key.group"] + cls.authorized_api_key_group = api_key_group_model.create( + { + "name": "Authorized api key group", + "code": "authorized_api_key_group", + "auth_api_key_ids": [(6, 0, cls.authorized_api_key.ids)], + } + ) + + def test_authenticated_auth_api_key(self): + # An exception is raised when no api key is used + with self.assertRaises(HTTPException) as error: + authenticated_auth_api_key(False, self.demo_env) + self.assertEqual(error.exception.detail, "No HTTP-API-KEY provided") + # An exception is raised when no api key record is found + with self.assertRaises(HTTPException) as error: + authenticated_auth_api_key("404", self.demo_env) + self.assertEqual(error.exception.detail, "The key 404 is not allowed") + # TODO enable this when we know how to filter keys based + # on endpoint's api key group. + # An exception is raised when unauthorized api key record is found + # with self.assertRaises(HTTPException) as error: + # authenticated_auth_api_key("not_authorized", self.demo_env) + result_key = authenticated_auth_api_key( + self.authorized_api_key.key, self.demo_env + ) + self.assertEqual(result_key, self.authorized_api_key) + + def test_authenticated_partner_by_api_key(self): + result_partner = authenticated_partner_by_api_key(self.authorized_api_key) + self.assertEqual(result_partner, self.authorized_user.partner_id) + + def test_authenticated_env_by_auth_api_key(self): + result_env = authenticated_env_by_auth_api_key(self.authorized_api_key) + self.assertEqual(result_env.user, self.authorized_user) diff --git a/fastapi_auth_api_key/views/fastapi_endpoint.xml b/fastapi_auth_api_key/views/fastapi_endpoint.xml new file mode 100644 index 000000000..bd8ba2a90 --- /dev/null +++ b/fastapi_auth_api_key/views/fastapi_endpoint.xml @@ -0,0 +1,17 @@ + + + + + + fastapi.endpoint.form.inherit + fastapi.endpoint + + + + + + + + + From f907630e09a7798490f31668da9c6f9e9a8f6abd Mon Sep 17 00:00:00 2001 From: sonhd91 Date: Fri, 24 May 2024 18:30:22 +0700 Subject: [PATCH 02/12] [IMP] fastapi_auth_api_key: pre-commit auto fixes --- fastapi_auth_api_key/README.rst | 121 ++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) diff --git a/fastapi_auth_api_key/README.rst b/fastapi_auth_api_key/README.rst index e69de29bb..bd0a9aaf7 100644 --- a/fastapi_auth_api_key/README.rst +++ b/fastapi_auth_api_key/README.rst @@ -0,0 +1,121 @@ +==================== +Fastapi Auth Api Key +==================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:a1a8681b1c3e7a13dc83e2e61a1d78ad8c8da1ddb684c8cf563607e96cf4f7e7 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Frest--framework-lightgray.png?logo=github + :target: https://github.com/OCA/rest-framework/tree/16.0/fastapi_auth_api_key + :alt: OCA/rest-framework +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/rest-framework-16-0/rest-framework-16-0-fastapi_auth_api_key + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/rest-framework&target_branch=16.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +Provides `FastAPI` dependencies for Api Key authentication. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +Getting an odoo environment +=========================== + +If you need to get an odoo env based on the provided api key, you can use `authenticated_env_by_auth_api_key`. + +.. code-block:: python + + @router.get("/example_with_authenticated_env") + def example_with_authenticated_env( + env: Annotated[Environment, Depends(authenticated_env_by_auth_api_key)], + ) -> None: + # env.user is the user attached to the provided key + pass + +Getting the authenticated partner +================================= + +If want to get the partned related to the the provided api key, you can use `authenticated_partner_by_api_key` + +.. code-block:: python + + @router.get("/example_with_authenticated_partner") + def example_with_authenticated_partner( + partner: Annotated[Partner, Depends(authenticated_partner_by_api_key)], + ) -> None: + # partner is the partner related to the provided key key.user_id.partner_id + pass + +Configuration +============= + +For this to work, the api key must be defined on the `Endpoint`. +A new field `auth_api_key_group_id` has been added to the `Endpoint` model. + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* Camptocamp + +Contributors +~~~~~~~~~~~~ + +* Matthieu Méquignon + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +.. |maintainer-mmequignon| image:: https://github.com/mmequignon.png?size=40px + :target: https://github.com/mmequignon + :alt: mmequignon + +Current `maintainer `__: + +|maintainer-mmequignon| + +This module is part of the `OCA/rest-framework `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. From 34776c1cae740b84360073c14b2aa557035f2c4e Mon Sep 17 00:00:00 2001 From: sonhd91 Date: Fri, 24 May 2024 18:23:29 +0700 Subject: [PATCH 03/12] [MIG] fastapi_auth_api_key: Migration to 17.0 --- fastapi_auth_api_key/README.rst | 71 +++++++++++-------- fastapi_auth_api_key/__manifest__.py | 2 +- fastapi_auth_api_key/dependencies.py | 4 +- fastapi_auth_api_key/pyproject.toml | 3 + fastapi_auth_api_key/readme/CONTRIBUTORS.md | 2 + fastapi_auth_api_key/readme/CONTRIBUTORS.rst | 1 - fastapi_auth_api_key/readme/CREDITS.md | 2 + fastapi_auth_api_key/readme/DESCRIPTION.md | 1 + fastapi_auth_api_key/readme/DESCRIPTION.rst | 1 - fastapi_auth_api_key/readme/USAGE.md | 32 +++++++++ fastapi_auth_api_key/readme/USAGE.rst | 33 --------- .../test_fastapi_api_key_dependencies.py | 22 ++++-- .../views/fastapi_endpoint.xml | 2 +- 13 files changed, 101 insertions(+), 75 deletions(-) create mode 100644 fastapi_auth_api_key/pyproject.toml create mode 100644 fastapi_auth_api_key/readme/CONTRIBUTORS.md delete mode 100644 fastapi_auth_api_key/readme/CONTRIBUTORS.rst create mode 100644 fastapi_auth_api_key/readme/CREDITS.md create mode 100644 fastapi_auth_api_key/readme/DESCRIPTION.md delete mode 100644 fastapi_auth_api_key/readme/DESCRIPTION.rst create mode 100644 fastapi_auth_api_key/readme/USAGE.md delete mode 100644 fastapi_auth_api_key/readme/USAGE.rst diff --git a/fastapi_auth_api_key/README.rst b/fastapi_auth_api_key/README.rst index bd0a9aaf7..f97f63c53 100644 --- a/fastapi_auth_api_key/README.rst +++ b/fastapi_auth_api_key/README.rst @@ -17,18 +17,18 @@ Fastapi Auth Api Key :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Frest--framework-lightgray.png?logo=github - :target: https://github.com/OCA/rest-framework/tree/16.0/fastapi_auth_api_key + :target: https://github.com/OCA/rest-framework/tree/17.0/fastapi_auth_api_key :alt: OCA/rest-framework .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/rest-framework-16-0/rest-framework-16-0-fastapi_auth_api_key + :target: https://translation.odoo-community.org/projects/rest-framework-17-0/rest-framework-17-0-fastapi_auth_api_key :alt: Translate me on Weblate .. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png - :target: https://runboat.odoo-community.org/builds?repo=OCA/rest-framework&target_branch=16.0 + :target: https://runboat.odoo-community.org/builds?repo=OCA/rest-framework&target_branch=17.0 :alt: Try me on Runboat |badge1| |badge2| |badge3| |badge4| |badge5| -Provides `FastAPI` dependencies for Api Key authentication. +Provides FastAPI dependencies for Api Key authentication. **Table of contents** @@ -39,38 +39,40 @@ Usage ===== Getting an odoo environment -=========================== +--------------------------- -If you need to get an odoo env based on the provided api key, you can use `authenticated_env_by_auth_api_key`. +If you need to get an odoo env based on the provided api key, you can +use authenticated_env_by_auth_api_key. -.. code-block:: python +.. code:: python - @router.get("/example_with_authenticated_env") - def example_with_authenticated_env( - env: Annotated[Environment, Depends(authenticated_env_by_auth_api_key)], - ) -> None: - # env.user is the user attached to the provided key - pass + @router.get("/example_with_authenticated_env") + def example_with_authenticated_env( + env: Annotated[Environment, Depends(authenticated_env_by_auth_api_key)], + ) -> None: + # env.user is the user attached to the provided key + pass Getting the authenticated partner -================================= +--------------------------------- -If want to get the partned related to the the provided api key, you can use `authenticated_partner_by_api_key` +If want to get the partned related to the the provided api key, you can +use authenticated_partner_by_api_key -.. code-block:: python +.. code:: python - @router.get("/example_with_authenticated_partner") - def example_with_authenticated_partner( - partner: Annotated[Partner, Depends(authenticated_partner_by_api_key)], - ) -> None: - # partner is the partner related to the provided key key.user_id.partner_id - pass + @router.get("/example_with_authenticated_partner") + def example_with_authenticated_partner( + partner: Annotated[Partner, Depends(authenticated_partner_by_api_key)], + ) -> None: + # partner is the partner related to the provided key key.user_id.partner_id + pass Configuration -============= +------------- -For this to work, the api key must be defined on the `Endpoint`. -A new field `auth_api_key_group_id` has been added to the `Endpoint` model. +For this to work, the api key must be defined on the Endpoint. A new +field auth_api_key_group_id has been added to the Endpoint model. Bug Tracker =========== @@ -78,7 +80,7 @@ Bug Tracker Bugs are tracked on `GitHub Issues `_. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed -`feedback `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -86,17 +88,24 @@ Credits ======= Authors -~~~~~~~ +------- * Camptocamp Contributors -~~~~~~~~~~~~ +------------ -* Matthieu Méquignon +- Matthieu Méquignon +- Son Ho + +Other credits +------------- + +The migration of this module from 16.0 to 17.0 was financially supported +by Camptocamp Maintainers -~~~~~~~~~~~ +----------- This module is maintained by the OCA. @@ -116,6 +125,6 @@ Current `maintainer `__: |maintainer-mmequignon| -This module is part of the `OCA/rest-framework `_ project on GitHub. +This module is part of the `OCA/rest-framework `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/fastapi_auth_api_key/__manifest__.py b/fastapi_auth_api_key/__manifest__.py index 1735c59be..539efdcc1 100644 --- a/fastapi_auth_api_key/__manifest__.py +++ b/fastapi_auth_api_key/__manifest__.py @@ -3,7 +3,7 @@ { "name": "Fastapi Auth Api Key", - "version": "16.0.1.0.0", + "version": "17.0.1.0.0", "category": "Others", "website": "https://github.com/OCA/rest-framework", "author": "Camptocamp, Odoo Community Association (OCA)", diff --git a/fastapi_auth_api_key/dependencies.py b/fastapi_auth_api_key/dependencies.py index 3b71e6d58..aa1838ab0 100644 --- a/fastapi_auth_api_key/dependencies.py +++ b/fastapi_auth_api_key/dependencies.py @@ -1,7 +1,7 @@ # Copyright 2024 Camptocamp SA # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) -from typing_extensions import Annotated +from typing import Annotated from odoo import SUPERUSER_ID from odoo.api import Environment @@ -34,7 +34,7 @@ def authenticated_auth_api_key( except ValidationError as error: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, - detail=error.name, + detail=error.args, headers={"WWW-Authenticate": "HTTP-API-KEY"}, ) from error # Ensure the api key is authorized for the current endpoint. diff --git a/fastapi_auth_api_key/pyproject.toml b/fastapi_auth_api_key/pyproject.toml new file mode 100644 index 000000000..4231d0ccc --- /dev/null +++ b/fastapi_auth_api_key/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/fastapi_auth_api_key/readme/CONTRIBUTORS.md b/fastapi_auth_api_key/readme/CONTRIBUTORS.md new file mode 100644 index 000000000..a6f2fed34 --- /dev/null +++ b/fastapi_auth_api_key/readme/CONTRIBUTORS.md @@ -0,0 +1,2 @@ +- Matthieu Méquignon \<\> +- Son Ho \<\> diff --git a/fastapi_auth_api_key/readme/CONTRIBUTORS.rst b/fastapi_auth_api_key/readme/CONTRIBUTORS.rst deleted file mode 100644 index bca4ee0ca..000000000 --- a/fastapi_auth_api_key/readme/CONTRIBUTORS.rst +++ /dev/null @@ -1 +0,0 @@ -* Matthieu Méquignon diff --git a/fastapi_auth_api_key/readme/CREDITS.md b/fastapi_auth_api_key/readme/CREDITS.md new file mode 100644 index 000000000..7c48f8e03 --- /dev/null +++ b/fastapi_auth_api_key/readme/CREDITS.md @@ -0,0 +1,2 @@ +The migration of this module from 16.0 to 17.0 was financially supported +by Camptocamp diff --git a/fastapi_auth_api_key/readme/DESCRIPTION.md b/fastapi_auth_api_key/readme/DESCRIPTION.md new file mode 100644 index 000000000..1e9aa6910 --- /dev/null +++ b/fastapi_auth_api_key/readme/DESCRIPTION.md @@ -0,0 +1 @@ +Provides FastAPI dependencies for Api Key authentication. diff --git a/fastapi_auth_api_key/readme/DESCRIPTION.rst b/fastapi_auth_api_key/readme/DESCRIPTION.rst deleted file mode 100644 index 22e772df2..000000000 --- a/fastapi_auth_api_key/readme/DESCRIPTION.rst +++ /dev/null @@ -1 +0,0 @@ -Provides `FastAPI` dependencies for Api Key authentication. diff --git a/fastapi_auth_api_key/readme/USAGE.md b/fastapi_auth_api_key/readme/USAGE.md new file mode 100644 index 000000000..f60799c41 --- /dev/null +++ b/fastapi_auth_api_key/readme/USAGE.md @@ -0,0 +1,32 @@ +## Getting an odoo environment + +If you need to get an odoo env based on the provided api key, you can +use authenticated_env_by_auth_api_key. + +``` python +@router.get("/example_with_authenticated_env") +def example_with_authenticated_env( + env: Annotated[Environment, Depends(authenticated_env_by_auth_api_key)], +) -> None: + # env.user is the user attached to the provided key + pass +``` + +## Getting the authenticated partner + +If want to get the partned related to the the provided api key, you can +use authenticated_partner_by_api_key + +``` python +@router.get("/example_with_authenticated_partner") +def example_with_authenticated_partner( + partner: Annotated[Partner, Depends(authenticated_partner_by_api_key)], +) -> None: + # partner is the partner related to the provided key key.user_id.partner_id + pass +``` + +## Configuration + +For this to work, the api key must be defined on the Endpoint. A new +field auth_api_key_group_id has been added to the Endpoint model. diff --git a/fastapi_auth_api_key/readme/USAGE.rst b/fastapi_auth_api_key/readme/USAGE.rst deleted file mode 100644 index 356cb02d2..000000000 --- a/fastapi_auth_api_key/readme/USAGE.rst +++ /dev/null @@ -1,33 +0,0 @@ -Getting an odoo environment -=========================== - -If you need to get an odoo env based on the provided api key, you can use `authenticated_env_by_auth_api_key`. - -.. code-block:: python - - @router.get("/example_with_authenticated_env") - def example_with_authenticated_env( - env: Annotated[Environment, Depends(authenticated_env_by_auth_api_key)], - ) -> None: - # env.user is the user attached to the provided key - pass - -Getting the authenticated partner -================================= - -If want to get the partned related to the the provided api key, you can use `authenticated_partner_by_api_key` - -.. code-block:: python - - @router.get("/example_with_authenticated_partner") - def example_with_authenticated_partner( - partner: Annotated[Partner, Depends(authenticated_partner_by_api_key)], - ) -> None: - # partner is the partner related to the provided key key.user_id.partner_id - pass - -Configuration -============= - -For this to work, the api key must be defined on the `Endpoint`. -A new field `auth_api_key_group_id` has been added to the `Endpoint` model. diff --git a/fastapi_auth_api_key/tests/test_fastapi_api_key_dependencies.py b/fastapi_auth_api_key/tests/test_fastapi_api_key_dependencies.py index d746e1ccc..dde6088ca 100644 --- a/fastapi_auth_api_key/tests/test_fastapi_api_key_dependencies.py +++ b/fastapi_auth_api_key/tests/test_fastapi_api_key_dependencies.py @@ -17,8 +17,17 @@ def setUpClass(cls): super().setUpClass() cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True)) # Is it valid? We need an env without superpowers - demo_user = cls.env.ref("base.partner_demo") + demo_user = cls.env.ref("base.user_demo") cls.demo_env = demo_user.with_user(demo_user).env + cls.demo_endpoint = cls.env["fastapi.endpoint"].create( + { + "name": "Test Enpoint", + "app": "demo", + "root_path": "/path_demo", + "demo_auth_method": "api_key", + "user_id": demo_user.id, + } + ) cls.setUpClassApiKey() @classmethod @@ -63,19 +72,22 @@ def setUpClassApiKey(cls): def test_authenticated_auth_api_key(self): # An exception is raised when no api key is used with self.assertRaises(HTTPException) as error: - authenticated_auth_api_key(False, self.demo_env) + authenticated_auth_api_key(False, self.demo_env, self.demo_endpoint) self.assertEqual(error.exception.detail, "No HTTP-API-KEY provided") # An exception is raised when no api key record is found with self.assertRaises(HTTPException) as error: - authenticated_auth_api_key("404", self.demo_env) - self.assertEqual(error.exception.detail, "The key 404 is not allowed") + authenticated_auth_api_key("404", self.demo_env, self.demo_endpoint) + self.assertEqual(error.exception.detail, ("The key 404 is not allowed",)) # TODO enable this when we know how to filter keys based # on endpoint's api key group. # An exception is raised when unauthorized api key record is found # with self.assertRaises(HTTPException) as error: # authenticated_auth_api_key("not_authorized", self.demo_env) + self.demo_endpoint.auth_api_key_group_id = ( + self.authorized_api_key.auth_api_key_group_ids[0] + ) result_key = authenticated_auth_api_key( - self.authorized_api_key.key, self.demo_env + self.authorized_api_key.key, self.demo_env, self.demo_endpoint ) self.assertEqual(result_key, self.authorized_api_key) diff --git a/fastapi_auth_api_key/views/fastapi_endpoint.xml b/fastapi_auth_api_key/views/fastapi_endpoint.xml index bd8ba2a90..1005dd501 100644 --- a/fastapi_auth_api_key/views/fastapi_endpoint.xml +++ b/fastapi_auth_api_key/views/fastapi_endpoint.xml @@ -8,7 +8,7 @@ fastapi.endpoint - + From 55cbcf0b72ab6c3f59978dece19bb80853a5de4e Mon Sep 17 00:00:00 2001 From: Pierre Verkest Date: Tue, 29 Jul 2025 11:11:20 +0200 Subject: [PATCH 04/12] [REF] fastapi_auth_api_key: review improvements --- fastapi_auth_api_key/README.rst | 6 +-- fastapi_auth_api_key/__manifest__.py | 2 +- fastapi_auth_api_key/dependencies.py | 24 +++++++----- .../models/fastapi_endpoint.py | 5 ++- .../test_fastapi_api_key_dependencies.py | 39 ++++++++++++------- 5 files changed, 48 insertions(+), 28 deletions(-) diff --git a/fastapi_auth_api_key/README.rst b/fastapi_auth_api_key/README.rst index f97f63c53..eb824b8ef 100644 --- a/fastapi_auth_api_key/README.rst +++ b/fastapi_auth_api_key/README.rst @@ -1,5 +1,5 @@ ==================== -Fastapi Auth Api Key +Fastapi Auth API Key ==================== .. @@ -95,8 +95,8 @@ Authors Contributors ------------ -- Matthieu Méquignon -- Son Ho +- Matthieu Méquignon +- Son Ho Other credits ------------- diff --git a/fastapi_auth_api_key/__manifest__.py b/fastapi_auth_api_key/__manifest__.py index 539efdcc1..f6136a6fe 100644 --- a/fastapi_auth_api_key/__manifest__.py +++ b/fastapi_auth_api_key/__manifest__.py @@ -2,7 +2,7 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) { - "name": "Fastapi Auth Api Key", + "name": "Fastapi Auth API Key", "version": "17.0.1.0.0", "category": "Others", "website": "https://github.com/OCA/rest-framework", diff --git a/fastapi_auth_api_key/dependencies.py b/fastapi_auth_api_key/dependencies.py index aa1838ab0..390c93a37 100644 --- a/fastapi_auth_api_key/dependencies.py +++ b/fastapi_auth_api_key/dependencies.py @@ -1,9 +1,9 @@ # Copyright 2024 Camptocamp SA # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) - +import os from typing import Annotated -from odoo import SUPERUSER_ID +from odoo import SUPERUSER_ID, _ from odoo.api import Environment from odoo.exceptions import ValidationError @@ -16,17 +16,20 @@ from fastapi.exceptions import HTTPException from fastapi.security import APIKeyHeader +HTTP_API_KEY_HEADER = os.environ.get("FASTAPI_AUTH_HTTP_API_KEY_HEADER", "HTTP-API-KEY") + def authenticated_auth_api_key( - key: Annotated[str, Depends(APIKeyHeader(name="HTTP-API-KEY"))], + key: Annotated[str, Depends(APIKeyHeader(name=HTTP_API_KEY_HEADER))], env: Annotated[Environment, Depends(odoo_env)], endpoint: Annotated[FastapiEndpoint, Depends(fastapi_endpoint)], ) -> AuthApiKey: if not key: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, - detail="No HTTP-API-KEY provided", - headers={"WWW-Authenticate": "HTTP-API-KEY"}, + detail=_("Missing %(HTTP_API_KEY_HEADER)s header") + % {"HTTP_API_KEY_HEADER": HTTP_API_KEY_HEADER}, + headers={"WWW-Authenticate": HTTP_API_KEY_HEADER}, ) admin_env = Environment(env.cr, SUPERUSER_ID, {}) try: @@ -35,14 +38,17 @@ def authenticated_auth_api_key( raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail=error.args, - headers={"WWW-Authenticate": "HTTP-API-KEY"}, + headers={"WWW-Authenticate": HTTP_API_KEY_HEADER}, ) from error # Ensure the api key is authorized for the current endpoint. - if auth_api_key not in endpoint.sudo().auth_api_key_group_id.auth_api_key_ids: + if ( + endpoint.sudo().auth_api_key_group_id + and auth_api_key not in endpoint.sudo().auth_api_key_group_id.auth_api_key_ids + ): raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, - detail="Unauthorized", - headers={"WWW-Authenticate": "HTTP-API-KEY"}, + detail=_("Unauthorized"), + headers={"WWW-Authenticate": HTTP_API_KEY_HEADER}, ) return auth_api_key diff --git a/fastapi_auth_api_key/models/fastapi_endpoint.py b/fastapi_auth_api_key/models/fastapi_endpoint.py index 8da7ff66d..697717ff5 100644 --- a/fastapi_auth_api_key/models/fastapi_endpoint.py +++ b/fastapi_auth_api_key/models/fastapi_endpoint.py @@ -7,4 +7,7 @@ class FastapiEndpoint(models.Model): _inherit = "fastapi.endpoint" - auth_api_key_group_id = fields.Many2one("auth.api.key.group") + auth_api_key_group_id = fields.Many2one( + "auth.api.key.group", + help="If not set, all 'auth.api.key' are allowed to access to endpoints", + ) diff --git a/fastapi_auth_api_key/tests/test_fastapi_api_key_dependencies.py b/fastapi_auth_api_key/tests/test_fastapi_api_key_dependencies.py index dde6088ca..54a297f2f 100644 --- a/fastapi_auth_api_key/tests/test_fastapi_api_key_dependencies.py +++ b/fastapi_auth_api_key/tests/test_fastapi_api_key_dependencies.py @@ -1,14 +1,14 @@ from odoo.tests import tagged from odoo.tests.common import TransactionCase -from fastapi.exceptions import HTTPException - -from ..dependencies import ( +from odoo.addons.fastapi_auth_api_key.dependencies import ( authenticated_auth_api_key, authenticated_env_by_auth_api_key, authenticated_partner_by_api_key, ) +from fastapi.exceptions import HTTPException + @tagged("-at_install", "post_install") class TestFastapiAuthApiKey(TransactionCase): @@ -16,7 +16,6 @@ class TestFastapiAuthApiKey(TransactionCase): def setUpClass(cls): super().setUpClass() cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True)) - # Is it valid? We need an env without superpowers demo_user = cls.env.ref("base.user_demo") cls.demo_env = demo_user.with_user(demo_user).env cls.demo_endpoint = cls.env["fastapi.endpoint"].create( @@ -68,29 +67,41 @@ def setUpClassApiKey(cls): "auth_api_key_ids": [(6, 0, cls.authorized_api_key.ids)], } ) + cls.demo_endpoint.auth_api_key_group_id = cls.authorized_api_key_group - def test_authenticated_auth_api_key(self): + def test_authenticated_auth_api_key_no_api_key(self): # An exception is raised when no api key is used with self.assertRaises(HTTPException) as error: authenticated_auth_api_key(False, self.demo_env, self.demo_endpoint) - self.assertEqual(error.exception.detail, "No HTTP-API-KEY provided") + self.assertEqual(error.exception.detail, "Missing HTTP-API-KEY header") + + def test_authenticated_auth_api_key_no_api_key_found(self): # An exception is raised when no api key record is found with self.assertRaises(HTTPException) as error: authenticated_auth_api_key("404", self.demo_env, self.demo_endpoint) self.assertEqual(error.exception.detail, ("The key 404 is not allowed",)) - # TODO enable this when we know how to filter keys based - # on endpoint's api key group. + + def test_authenticated_auth_api_key_unauthorized_key(self): # An exception is raised when unauthorized api key record is found - # with self.assertRaises(HTTPException) as error: - # authenticated_auth_api_key("not_authorized", self.demo_env) - self.demo_endpoint.auth_api_key_group_id = ( - self.authorized_api_key.auth_api_key_group_ids[0] - ) + with self.assertRaisesRegex(HTTPException, r"Unauthorized"): + authenticated_auth_api_key( + "unauthorized_key", self.demo_env, self.demo_endpoint + ) + + def test_authenticated_auth_api_key(self): result_key = authenticated_auth_api_key( - self.authorized_api_key.key, self.demo_env, self.demo_endpoint + "authorized_key", self.demo_env, self.demo_endpoint ) self.assertEqual(result_key, self.authorized_api_key) + def test_authenticated_auth_api_key_without_group(self): + # test with no group set unauthorized is allow to access + self.demo_endpoint.auth_api_key_group_id = False + result_key = authenticated_auth_api_key( + "unauthorized_key", self.demo_env, self.demo_endpoint + ) + self.assertEqual(result_key, self.unauthorized_api_key) + def test_authenticated_partner_by_api_key(self): result_partner = authenticated_partner_by_api_key(self.authorized_api_key) self.assertEqual(result_partner, self.authorized_user.partner_id) From 03c1ef70995a3acfc0afb25c61daed4cf4ed8f54 Mon Sep 17 00:00:00 2001 From: Pierre Verkest Date: Mon, 8 Sep 2025 14:41:20 +0200 Subject: [PATCH 05/12] [FIX] freeze graphql_server --- fastapi_auth_api_key/README.rst | 10 +++++----- fastapi_auth_api_key/dependencies.py | 4 ++-- .../views/fastapi_endpoint.xml | 18 ++++++++---------- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/fastapi_auth_api_key/README.rst b/fastapi_auth_api_key/README.rst index eb824b8ef..9ba58ac6b 100644 --- a/fastapi_auth_api_key/README.rst +++ b/fastapi_auth_api_key/README.rst @@ -17,13 +17,13 @@ Fastapi Auth API Key :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Frest--framework-lightgray.png?logo=github - :target: https://github.com/OCA/rest-framework/tree/17.0/fastapi_auth_api_key + :target: https://github.com/OCA/rest-framework/tree/18.0/fastapi_auth_api_key :alt: OCA/rest-framework .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/rest-framework-17-0/rest-framework-17-0-fastapi_auth_api_key + :target: https://translation.odoo-community.org/projects/rest-framework-18-0/rest-framework-18-0-fastapi_auth_api_key :alt: Translate me on Weblate .. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png - :target: https://runboat.odoo-community.org/builds?repo=OCA/rest-framework&target_branch=17.0 + :target: https://runboat.odoo-community.org/builds?repo=OCA/rest-framework&target_branch=18.0 :alt: Try me on Runboat |badge1| |badge2| |badge3| |badge4| |badge5| @@ -80,7 +80,7 @@ Bug Tracker Bugs are tracked on `GitHub Issues `_. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed -`feedback `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -125,6 +125,6 @@ Current `maintainer `__: |maintainer-mmequignon| -This module is part of the `OCA/rest-framework `_ project on GitHub. +This module is part of the `OCA/rest-framework `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/fastapi_auth_api_key/dependencies.py b/fastapi_auth_api_key/dependencies.py index 390c93a37..8e2604d20 100644 --- a/fastapi_auth_api_key/dependencies.py +++ b/fastapi_auth_api_key/dependencies.py @@ -54,13 +54,13 @@ def authenticated_auth_api_key( def authenticated_partner_by_api_key( - auth_api_key: Annotated[AuthApiKey, Depends(authenticated_auth_api_key)] + auth_api_key: Annotated[AuthApiKey, Depends(authenticated_auth_api_key)], ) -> Partner: return auth_api_key.user_id.partner_id def authenticated_env_by_auth_api_key( - auth_api_key: Annotated[AuthApiKey, Depends(authenticated_auth_api_key)] + auth_api_key: Annotated[AuthApiKey, Depends(authenticated_auth_api_key)], ) -> Environment: # set api key id in context return auth_api_key.with_user(auth_api_key.user_id).env diff --git a/fastapi_auth_api_key/views/fastapi_endpoint.xml b/fastapi_auth_api_key/views/fastapi_endpoint.xml index 1005dd501..ede290377 100644 --- a/fastapi_auth_api_key/views/fastapi_endpoint.xml +++ b/fastapi_auth_api_key/views/fastapi_endpoint.xml @@ -2,16 +2,14 @@ - - fastapi.endpoint.form.inherit - fastapi.endpoint - - - - - - + fastapi.endpoint.form.inherit + fastapi.endpoint + + + + + + - From 24ba923a3ed5983b07a7b9bcf97de4d0d0dbaf2e Mon Sep 17 00:00:00 2001 From: Maksym Yankin Date: Thu, 2 Oct 2025 13:17:00 +0300 Subject: [PATCH 06/12] [MIG] fastapi_auth_api_key: Migration to 18.0 status.HTTP_422_UNPROCESSABLE_ENTITY is deprecated --- fastapi_auth_api_key/README.rst | 2 +- fastapi_auth_api_key/__manifest__.py | 2 +- fastapi_auth_api_key/dependencies.py | 6 +++--- fastapi_auth_api_key/readme/CREDITS.md | 2 +- fastapi_auth_api_key/static/description/index.html | 1 - 5 files changed, 6 insertions(+), 7 deletions(-) diff --git a/fastapi_auth_api_key/README.rst b/fastapi_auth_api_key/README.rst index 9ba58ac6b..5511f577c 100644 --- a/fastapi_auth_api_key/README.rst +++ b/fastapi_auth_api_key/README.rst @@ -101,7 +101,7 @@ Contributors Other credits ------------- -The migration of this module from 16.0 to 17.0 was financially supported +The migration of this module from 17.0 to 18.0 was financially supported by Camptocamp Maintainers diff --git a/fastapi_auth_api_key/__manifest__.py b/fastapi_auth_api_key/__manifest__.py index f6136a6fe..162e4649d 100644 --- a/fastapi_auth_api_key/__manifest__.py +++ b/fastapi_auth_api_key/__manifest__.py @@ -3,7 +3,7 @@ { "name": "Fastapi Auth API Key", - "version": "17.0.1.0.0", + "version": "18.0.1.0.0", "category": "Others", "website": "https://github.com/OCA/rest-framework", "author": "Camptocamp, Odoo Community Association (OCA)", diff --git a/fastapi_auth_api_key/dependencies.py b/fastapi_auth_api_key/dependencies.py index 8e2604d20..6f77bf707 100644 --- a/fastapi_auth_api_key/dependencies.py +++ b/fastapi_auth_api_key/dependencies.py @@ -3,7 +3,7 @@ import os from typing import Annotated -from odoo import SUPERUSER_ID, _ +from odoo import SUPERUSER_ID from odoo.api import Environment from odoo.exceptions import ValidationError @@ -27,7 +27,7 @@ def authenticated_auth_api_key( if not key: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, - detail=_("Missing %(HTTP_API_KEY_HEADER)s header") + detail=env._("Missing %(HTTP_API_KEY_HEADER)s header") % {"HTTP_API_KEY_HEADER": HTTP_API_KEY_HEADER}, headers={"WWW-Authenticate": HTTP_API_KEY_HEADER}, ) @@ -47,7 +47,7 @@ def authenticated_auth_api_key( ): raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, - detail=_("Unauthorized"), + detail=env._("Unauthorized"), headers={"WWW-Authenticate": HTTP_API_KEY_HEADER}, ) return auth_api_key diff --git a/fastapi_auth_api_key/readme/CREDITS.md b/fastapi_auth_api_key/readme/CREDITS.md index 7c48f8e03..76edf6308 100644 --- a/fastapi_auth_api_key/readme/CREDITS.md +++ b/fastapi_auth_api_key/readme/CREDITS.md @@ -1,2 +1,2 @@ -The migration of this module from 16.0 to 17.0 was financially supported +The migration of this module from 17.0 to 18.0 was financially supported by Camptocamp diff --git a/fastapi_auth_api_key/static/description/index.html b/fastapi_auth_api_key/static/description/index.html index ec3643de8..04faf101c 100644 --- a/fastapi_auth_api_key/static/description/index.html +++ b/fastapi_auth_api_key/static/description/index.html @@ -1,4 +1,3 @@ - From 7be4bfc89dbad5943433e3fccd27150161fb26a0 Mon Sep 17 00:00:00 2001 From: oca-ci Date: Fri, 24 Oct 2025 10:19:14 +0000 Subject: [PATCH 07/12] [UPD] Update fastapi_auth_api_key.pot --- .../i18n/fastapi_auth_api_key.pot | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 fastapi_auth_api_key/i18n/fastapi_auth_api_key.pot diff --git a/fastapi_auth_api_key/i18n/fastapi_auth_api_key.pot b/fastapi_auth_api_key/i18n/fastapi_auth_api_key.pot new file mode 100644 index 000000000..bc50a1d31 --- /dev/null +++ b/fastapi_auth_api_key/i18n/fastapi_auth_api_key.pot @@ -0,0 +1,41 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * fastapi_auth_api_key +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 18.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: fastapi_auth_api_key +#: model:ir.model.fields,field_description:fastapi_auth_api_key.field_fastapi_endpoint__auth_api_key_group_id +msgid "Auth Api Key Group" +msgstr "" + +#. module: fastapi_auth_api_key +#: model:ir.model,name:fastapi_auth_api_key.model_fastapi_endpoint +msgid "FastAPI Endpoint" +msgstr "" + +#. module: fastapi_auth_api_key +#: model:ir.model.fields,help:fastapi_auth_api_key.field_fastapi_endpoint__auth_api_key_group_id +msgid "If not set, all 'auth.api.key' are allowed to access to endpoints" +msgstr "" + +#. module: fastapi_auth_api_key +#. odoo-python +#: code:addons/fastapi_auth_api_key/dependencies.py:0 +msgid "Missing %(HTTP_API_KEY_HEADER)s header" +msgstr "" + +#. module: fastapi_auth_api_key +#. odoo-python +#: code:addons/fastapi_auth_api_key/dependencies.py:0 +msgid "Unauthorized" +msgstr "" From dd738d3fa428a102381e3fd8e6e8ffd5d9bc945e Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Fri, 24 Oct 2025 10:21:24 +0000 Subject: [PATCH 08/12] [BOT] post-merge updates --- fastapi_auth_api_key/README.rst | 8 ++++++-- .../static/description/icon.png | Bin 0 -> 10254 bytes 2 files changed, 6 insertions(+), 2 deletions(-) create mode 100644 fastapi_auth_api_key/static/description/icon.png diff --git a/fastapi_auth_api_key/README.rst b/fastapi_auth_api_key/README.rst index 5511f577c..a615c5fc2 100644 --- a/fastapi_auth_api_key/README.rst +++ b/fastapi_auth_api_key/README.rst @@ -1,3 +1,7 @@ +.. image:: https://odoo-community.org/readme-banner-image + :target: https://odoo-community.org/get-involved?utm_source=readme + :alt: Odoo Community Association + ==================== Fastapi Auth API Key ==================== @@ -7,13 +11,13 @@ Fastapi Auth API Key !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:a1a8681b1c3e7a13dc83e2e61a1d78ad8c8da1ddb684c8cf563607e96cf4f7e7 + !! source digest: sha256:48191f57e5bf9c229b23db831db547eb150706930ed1dbafdc5386025ee20d09 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png :target: https://odoo-community.org/page/development-status :alt: Beta -.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png +.. |badge2| image:: https://img.shields.io/badge/license-AGPL--3-blue.png :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Frest--framework-lightgray.png?logo=github diff --git a/fastapi_auth_api_key/static/description/icon.png b/fastapi_auth_api_key/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..1dcc49c24f364e9adf0afbc6fc0bac6dbecdeb11 GIT binary patch literal 10254 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 Date: Mon, 27 Oct 2025 12:42:02 +0000 Subject: [PATCH 09/12] Added translation using Weblate (Italian) --- fastapi_auth_api_key/i18n/it.po | 42 +++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 fastapi_auth_api_key/i18n/it.po diff --git a/fastapi_auth_api_key/i18n/it.po b/fastapi_auth_api_key/i18n/it.po new file mode 100644 index 000000000..518c2c88f --- /dev/null +++ b/fastapi_auth_api_key/i18n/it.po @@ -0,0 +1,42 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * fastapi_auth_api_key +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 18.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +#. module: fastapi_auth_api_key +#: model:ir.model.fields,field_description:fastapi_auth_api_key.field_fastapi_endpoint__auth_api_key_group_id +msgid "Auth Api Key Group" +msgstr "" + +#. module: fastapi_auth_api_key +#: model:ir.model,name:fastapi_auth_api_key.model_fastapi_endpoint +msgid "FastAPI Endpoint" +msgstr "" + +#. module: fastapi_auth_api_key +#: model:ir.model.fields,help:fastapi_auth_api_key.field_fastapi_endpoint__auth_api_key_group_id +msgid "If not set, all 'auth.api.key' are allowed to access to endpoints" +msgstr "" + +#. module: fastapi_auth_api_key +#. odoo-python +#: code:addons/fastapi_auth_api_key/dependencies.py:0 +msgid "Missing %(HTTP_API_KEY_HEADER)s header" +msgstr "" + +#. module: fastapi_auth_api_key +#. odoo-python +#: code:addons/fastapi_auth_api_key/dependencies.py:0 +msgid "Unauthorized" +msgstr "" From de52f7ece6c8bac204260a2abd86738416e55014 Mon Sep 17 00:00:00 2001 From: mymage Date: Thu, 6 Nov 2025 07:36:29 +0000 Subject: [PATCH 10/12] Translated using Weblate (Italian) Currently translated at 100.0% (5 of 5 strings) Translation: rest-framework-18.0/rest-framework-18.0-fastapi_auth_api_key Translate-URL: https://translation.odoo-community.org/projects/rest-framework-18-0/rest-framework-18-0-fastapi_auth_api_key/it/ --- fastapi_auth_api_key/i18n/it.po | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/fastapi_auth_api_key/i18n/it.po b/fastapi_auth_api_key/i18n/it.po index 518c2c88f..58c8f2c89 100644 --- a/fastapi_auth_api_key/i18n/it.po +++ b/fastapi_auth_api_key/i18n/it.po @@ -6,37 +6,41 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 18.0\n" "Report-Msgid-Bugs-To: \n" -"Last-Translator: Automatically generated\n" +"PO-Revision-Date: 2025-11-06 09:42+0000\n" +"Last-Translator: mymage \n" "Language-Team: none\n" "Language: it\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: \n" "Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 5.10.4\n" #. module: fastapi_auth_api_key #: model:ir.model.fields,field_description:fastapi_auth_api_key.field_fastapi_endpoint__auth_api_key_group_id msgid "Auth Api Key Group" -msgstr "" +msgstr "Gruppo chiave API autorizzazione" #. module: fastapi_auth_api_key #: model:ir.model,name:fastapi_auth_api_key.model_fastapi_endpoint msgid "FastAPI Endpoint" -msgstr "" +msgstr "Endopoint FastAPI" #. module: fastapi_auth_api_key #: model:ir.model.fields,help:fastapi_auth_api_key.field_fastapi_endpoint__auth_api_key_group_id msgid "If not set, all 'auth.api.key' are allowed to access to endpoints" msgstr "" +"Se non impostata, tutte le 'auth.api.key' sono abilitate ad accedere agli " +"endpoint" #. module: fastapi_auth_api_key #. odoo-python #: code:addons/fastapi_auth_api_key/dependencies.py:0 msgid "Missing %(HTTP_API_KEY_HEADER)s header" -msgstr "" +msgstr "Header %(HTTP_API_KEY_HEADER)s mancante" #. module: fastapi_auth_api_key #. odoo-python #: code:addons/fastapi_auth_api_key/dependencies.py:0 msgid "Unauthorized" -msgstr "" +msgstr "Non autorizzata" From 1756ff684129df7efdde503fb42b7cb6244833cb Mon Sep 17 00:00:00 2001 From: mymage Date: Wed, 10 Dec 2025 09:37:09 +0000 Subject: [PATCH 11/12] Translated using Weblate (Italian) Currently translated at 100.0% (5 of 5 strings) Translation: rest-framework-18.0/rest-framework-18.0-fastapi_auth_api_key Translate-URL: https://translation.odoo-community.org/projects/rest-framework-18-0/rest-framework-18-0-fastapi_auth_api_key/it/ --- fastapi_auth_api_key/i18n/it.po | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fastapi_auth_api_key/i18n/it.po b/fastapi_auth_api_key/i18n/it.po index 58c8f2c89..7c4040251 100644 --- a/fastapi_auth_api_key/i18n/it.po +++ b/fastapi_auth_api_key/i18n/it.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 18.0\n" "Report-Msgid-Bugs-To: \n" -"PO-Revision-Date: 2025-11-06 09:42+0000\n" +"PO-Revision-Date: 2025-12-10 11:43+0000\n" "Last-Translator: mymage \n" "Language-Team: none\n" "Language: it\n" @@ -24,7 +24,7 @@ msgstr "Gruppo chiave API autorizzazione" #. module: fastapi_auth_api_key #: model:ir.model,name:fastapi_auth_api_key.model_fastapi_endpoint msgid "FastAPI Endpoint" -msgstr "Endopoint FastAPI" +msgstr "Endpoint FastAPI" #. module: fastapi_auth_api_key #: model:ir.model.fields,help:fastapi_auth_api_key.field_fastapi_endpoint__auth_api_key_group_id From 16e8ee35ad6839687cbf963ab861198410d76246 Mon Sep 17 00:00:00 2001 From: Giuseppe Ardoselli Date: Wed, 17 Jun 2026 14:13:31 +0200 Subject: [PATCH 12/12] [MIG] fastapi_auth_api_key: Migration to 19.0 --- fastapi_auth_api_key/README.rst | 11 ++++++----- fastapi_auth_api_key/__manifest__.py | 2 +- fastapi_auth_api_key/dependencies.py | 13 ++++++++----- fastapi_auth_api_key/readme/CONTRIBUTORS.md | 1 + .../tests/test_fastapi_api_key_dependencies.py | 14 ++++++++++---- 5 files changed, 26 insertions(+), 15 deletions(-) diff --git a/fastapi_auth_api_key/README.rst b/fastapi_auth_api_key/README.rst index a615c5fc2..049556daa 100644 --- a/fastapi_auth_api_key/README.rst +++ b/fastapi_auth_api_key/README.rst @@ -21,13 +21,13 @@ Fastapi Auth API Key :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Frest--framework-lightgray.png?logo=github - :target: https://github.com/OCA/rest-framework/tree/18.0/fastapi_auth_api_key + :target: https://github.com/OCA/rest-framework/tree/19.0/fastapi_auth_api_key :alt: OCA/rest-framework .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/rest-framework-18-0/rest-framework-18-0-fastapi_auth_api_key + :target: https://translation.odoo-community.org/projects/rest-framework-19-0/rest-framework-19-0-fastapi_auth_api_key :alt: Translate me on Weblate .. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png - :target: https://runboat.odoo-community.org/builds?repo=OCA/rest-framework&target_branch=18.0 + :target: https://runboat.odoo-community.org/builds?repo=OCA/rest-framework&target_branch=19.0 :alt: Try me on Runboat |badge1| |badge2| |badge3| |badge4| |badge5| @@ -84,7 +84,7 @@ Bug Tracker Bugs are tracked on `GitHub Issues `_. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed -`feedback `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -101,6 +101,7 @@ Contributors - Matthieu Méquignon - Son Ho +- Giuseppe Ardoselli Other credits ------------- @@ -129,6 +130,6 @@ Current `maintainer `__: |maintainer-mmequignon| -This module is part of the `OCA/rest-framework `_ project on GitHub. +This module is part of the `OCA/rest-framework `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/fastapi_auth_api_key/__manifest__.py b/fastapi_auth_api_key/__manifest__.py index 162e4649d..63b66c6c4 100644 --- a/fastapi_auth_api_key/__manifest__.py +++ b/fastapi_auth_api_key/__manifest__.py @@ -3,7 +3,7 @@ { "name": "Fastapi Auth API Key", - "version": "18.0.1.0.0", + "version": "19.0.1.0.0", "category": "Others", "website": "https://github.com/OCA/rest-framework", "author": "Camptocamp, Odoo Community Association (OCA)", diff --git a/fastapi_auth_api_key/dependencies.py b/fastapi_auth_api_key/dependencies.py index 6f77bf707..1252d09a5 100644 --- a/fastapi_auth_api_key/dependencies.py +++ b/fastapi_auth_api_key/dependencies.py @@ -3,17 +3,18 @@ import os from typing import Annotated +from fastapi.exceptions import HTTPException + from odoo import SUPERUSER_ID from odoo.api import Environment from odoo.exceptions import ValidationError from odoo.addons.auth_api_key.models.auth_api_key import AuthApiKey -from odoo.addons.base.models.res_partner import Partner +from odoo.addons.base.models.res_partner import ResPartner from odoo.addons.fastapi.dependencies import fastapi_endpoint, odoo_env from odoo.addons.fastapi.models.fastapi_endpoint import FastapiEndpoint from fastapi import Depends, status -from fastapi.exceptions import HTTPException from fastapi.security import APIKeyHeader HTTP_API_KEY_HEADER = os.environ.get("FASTAPI_AUTH_HTTP_API_KEY_HEADER", "HTTP-API-KEY") @@ -27,8 +28,10 @@ def authenticated_auth_api_key( if not key: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, - detail=env._("Missing %(HTTP_API_KEY_HEADER)s header") - % {"HTTP_API_KEY_HEADER": HTTP_API_KEY_HEADER}, + detail=env._( + "Missing %(HTTP_API_KEY_HEADER)s header", + HTTP_API_KEY_HEADER=HTTP_API_KEY_HEADER, + ), headers={"WWW-Authenticate": HTTP_API_KEY_HEADER}, ) admin_env = Environment(env.cr, SUPERUSER_ID, {}) @@ -55,7 +58,7 @@ def authenticated_auth_api_key( def authenticated_partner_by_api_key( auth_api_key: Annotated[AuthApiKey, Depends(authenticated_auth_api_key)], -) -> Partner: +) -> ResPartner: return auth_api_key.user_id.partner_id diff --git a/fastapi_auth_api_key/readme/CONTRIBUTORS.md b/fastapi_auth_api_key/readme/CONTRIBUTORS.md index a6f2fed34..94b8fb85b 100644 --- a/fastapi_auth_api_key/readme/CONTRIBUTORS.md +++ b/fastapi_auth_api_key/readme/CONTRIBUTORS.md @@ -1,2 +1,3 @@ - Matthieu Méquignon \<\> - Son Ho \<\> +- Giuseppe Ardoselli \<\> diff --git a/fastapi_auth_api_key/tests/test_fastapi_api_key_dependencies.py b/fastapi_auth_api_key/tests/test_fastapi_api_key_dependencies.py index 54a297f2f..49a1c65f1 100644 --- a/fastapi_auth_api_key/tests/test_fastapi_api_key_dependencies.py +++ b/fastapi_auth_api_key/tests/test_fastapi_api_key_dependencies.py @@ -1,3 +1,5 @@ +from fastapi.exceptions import HTTPException + from odoo.tests import tagged from odoo.tests.common import TransactionCase @@ -7,8 +9,6 @@ authenticated_partner_by_api_key, ) -from fastapi.exceptions import HTTPException - @tagged("-at_install", "post_install") class TestFastapiAuthApiKey(TransactionCase): @@ -16,7 +16,13 @@ class TestFastapiAuthApiKey(TransactionCase): def setUpClass(cls): super().setUpClass() cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True)) - demo_user = cls.env.ref("base.user_demo") + # Odoo 19 no longer loads demo data by default, so we cannot rely on + # ``base.user_demo``; create a dedicated user instead. + demo_user = ( + cls.env["res.users"] + .with_context(no_reset_password=True) + .create({"name": "Endpoint Demo User", "login": "endpoint_demo_user"}) + ) cls.demo_env = demo_user.with_user(demo_user).env cls.demo_endpoint = cls.env["fastapi.endpoint"].create( { @@ -79,7 +85,7 @@ def test_authenticated_auth_api_key_no_api_key_found(self): # An exception is raised when no api key record is found with self.assertRaises(HTTPException) as error: authenticated_auth_api_key("404", self.demo_env, self.demo_endpoint) - self.assertEqual(error.exception.detail, ("The key 404 is not allowed",)) + self.assertEqual(error.exception.detail, ("The key '404' is not allowed",)) def test_authenticated_auth_api_key_unauthorized_key(self): # An exception is raised when unauthorized api key record is found