From 2b0bf7f42db5060eeaef2dd0bf40a94ae750d4cf Mon Sep 17 00:00:00 2001 From: Alexandre Fayolle Date: Wed, 28 Feb 2024 11:02:24 +0100 Subject: [PATCH] [IMP] webservice: add support for oauth2 --- requirements.txt | 1 + webservice/README.rst | 2 +- webservice/__manifest__.py | 1 + webservice/components/request_adapter.py | 43 ++++++++++++++++++------ webservice/models/webservice_backend.py | 11 ++++++ webservice/static/description/index.html | 3 +- webservice/views/webservice_backend.xml | 16 +++++++++ 7 files changed, 64 insertions(+), 13 deletions(-) diff --git a/requirements.txt b/requirements.txt index 9cd16292..ae0ca88c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,2 @@ # generated from manifests external_dependencies +requests-oauthlib diff --git a/webservice/README.rst b/webservice/README.rst index 202123ff..3754df1e 100644 --- a/webservice/README.rst +++ b/webservice/README.rst @@ -7,7 +7,7 @@ WebService !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:303644ddb310b8c13e53c0cec4ea4f665b2ebb8a86b0c17bae78968c38633f4b + !! source digest: sha256:d577a7b3d22d30b8093f1893c30ad9fa0a58622a3fd96520ad4a821dd1bdf197 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Production%2FStable-green.png diff --git a/webservice/__manifest__.py b/webservice/__manifest__.py index 89fd9fd1..2d667363 100644 --- a/webservice/__manifest__.py +++ b/webservice/__manifest__.py @@ -15,6 +15,7 @@ "author": "Creu Blanca, Camptocamp, Odoo Community Association (OCA)", "website": "https://github.com/OCA/web-api", "depends": ["component", "server_environment"], + "external_dependencies": {"python": ["requests-oauthlib"]}, "data": [ "security/ir.model.access.csv", "security/ir_rule.xml", diff --git a/webservice/components/request_adapter.py b/webservice/components/request_adapter.py index 4d7d00cb..4f6e6a08 100644 --- a/webservice/components/request_adapter.py +++ b/webservice/components/request_adapter.py @@ -4,6 +4,7 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). import requests +from requests_oauthlib import OAuth2Session from odoo.addons.component.core import Component @@ -15,19 +16,19 @@ class BaseRestRequestsAdapter(Component): # TODO: url and url_params could come from work_ctx def _request(self, method, url=None, url_params=None, **kwargs): + Session = self._get_session_class() url = self._get_url(url=url, url_params=url_params) new_kwargs = kwargs.copy() - new_kwargs.update( - { - "auth": self._get_auth(**kwargs), - "headers": self._get_headers(**kwargs), - "timeout": None, - } - ) - # pylint: disable=E8106 - request = requests.request(method, url, **new_kwargs) - request.raise_for_status() - return request.content + session_kwargs = { + "auth": self._get_auth(**kwargs), + "headers": self._get_headers(**kwargs), + "timeout": None, + } + with Session(**session_kwargs) as session: + # pylint: disable=E8106 + resp = session.request(method, url, **new_kwargs) + resp.raise_for_status() + return resp.content def get(self, **kwargs): return self._request("get", **kwargs) @@ -44,11 +45,31 @@ def _get_auth(self, auth=False, **kwargs): handler = getattr(self, "_get_auth_for_" + self.collection.auth_type, None) return handler(**kwargs) if handler else None + def _get_session_class(self): + handler = getattr( + self, "_get_session_class_for_" + self.collection.auth_type, None + ) + if handler is None: + return requests.Session + else: + return handler() + + def _get_session_class_for_oauth2(self): + return OAuth2Session + def _get_auth_for_user_pwd(self, **kw): if self.collection.username and self.collection.password: return self.collection.username, self.collection.password return None + def _get_auth_for_oauth2(self, **kwargs): + return { + "client_id": self.collection.oauth2_client_id, + "client_secret": self.collection.oauth2_client_secret, + "token_url": self.collection.oauth2_token_url, + "audience": self.collection.oaut2_audience, + } + def _get_headers(self, content_type=False, headers=False, **kwargs): headers = headers or {} result = { diff --git a/webservice/models/webservice_backend.py b/webservice/models/webservice_backend.py index 84567f96..68fa980e 100644 --- a/webservice/models/webservice_backend.py +++ b/webservice/models/webservice_backend.py @@ -21,6 +21,7 @@ class WebserviceBackend(models.Model): ("none", "Public"), ("user_pwd", "Username & password"), ("api_key", "API Key"), + ("oauth2", "OAuth2"), ], default="user_pwd", required=True, @@ -29,6 +30,12 @@ class WebserviceBackend(models.Model): password = fields.Char(auth_type="user_pwd") api_key = fields.Char(string="API Key", auth_type="api_key") api_key_header = fields.Char(string="API Key header", auth_type="api_key") + oauth2_clientid = fields.Char(string="Client ID", auth_type="oauth2") + oauth2_client_secret = fields.Char(string="Client Secret", auth_type="oauth2") + oauth2_token_url = fields.Char(string="Token URL", auth_type="oauth2") + oauth2_audience = fields.Char( + string="Token URL" + ) # no auth_type because not required content_type = fields.Selection( [ ("application/json", "JSON"), @@ -93,6 +100,10 @@ def _server_env_fields(self): "api_key": {}, "api_key_header": {}, "content_type": {}, + "oauth2_client_id": {}, + "oauth2_client_secret": {}, + "oauth2_token_url": {}, + "oauth2_audience": {}, } webservice_fields.update(base_fields) return webservice_fields diff --git a/webservice/static/description/index.html b/webservice/static/description/index.html index 6c33c234..e220f406 100644 --- a/webservice/static/description/index.html +++ b/webservice/static/description/index.html @@ -1,3 +1,4 @@ + @@ -366,7 +367,7 @@

WebService

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! source digest: sha256:303644ddb310b8c13e53c0cec4ea4f665b2ebb8a86b0c17bae78968c38633f4b +!! source digest: sha256:d577a7b3d22d30b8093f1893c30ad9fa0a58622a3fd96520ad4a821dd1bdf197 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->

Production/Stable License: AGPL-3 OCA/web-api Translate me on Weblate Try me on Runboat

This module creates WebService frameworks to be used globally

diff --git a/webservice/views/webservice_backend.xml b/webservice/views/webservice_backend.xml index 9fcf304e..a053cce8 100644 --- a/webservice/views/webservice_backend.xml +++ b/webservice/views/webservice_backend.xml @@ -58,6 +58,22 @@ 'required': [('auth_type', '=', 'api_key')], }" /> + + + +