diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 367dea5f5..d5d6f13ea 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,7 +1,6 @@ exclude: | (?x) # NOT INSTALLABLE ADDONS - ^base_rest/| ^base_rest_auth_api_key/| ^base_rest_pydantic/| ^extendable/| diff --git a/base_rest/README.rst b/base_rest/README.rst index 5f93be562..6cd9c1b39 100644 --- a/base_rest/README.rst +++ b/base_rest/README.rst @@ -21,13 +21,13 @@ Base Rest :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html :alt: License: LGPL-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/base_rest + :target: https://github.com/OCA/rest-framework/tree/19.0/base_rest :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-base_rest + :target: https://translation.odoo-community.org/projects/rest-framework-19-0/rest-framework-19-0-base_rest :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| @@ -89,8 +89,8 @@ Usage To add your own REST service you must provides at least 2 classes. -- A Component providing the business logic of your service, -- A Controller to register your service. +- A Component providing the business logic of your service, +- A Controller to register your service. The business logic of your service must be implemented into a component (``odoo.addons.component.core.Component``) that inherit from @@ -99,22 +99,22 @@ The business logic of your service must be implemented into a component Initially, base_rest expose by default all public methods defined in a service. The conventions for accessing methods via HTTP were as follows: -- The method ``def get(self, _id)`` if defined, is accessible via HTTP - GET routes ``/`` and - ``//get``. -- The method ``def search(self, **params)`` if defined, is accessible - via the HTTP GET routes ``/`` and - ``/search``. -- The method ``def delete(self, _id)`` if defined, is accessible via the - HTTP DELETE route ``/``. -- The ``def update(self, _id, **params)`` method, if defined, is - accessible via the HTTP PUT route - ``/``. -- Other methods are only accessible via HTTP POST routes - ```` or - ``/`` or - ``/`` or - ``//`` +- The method ``def get(self, _id)`` if defined, is accessible via HTTP + GET routes ``/`` and + ``//get``. +- The method ``def search(self, **params)`` if defined, is accessible + via the HTTP GET routes ``/`` and + ``/search``. +- The method ``def delete(self, _id)`` if defined, is accessible via + the HTTP DELETE route ``/``. +- The ``def update(self, _id, **params)`` method, if defined, is + accessible via the HTTP PUT route + ``/``. +- Other methods are only accessible via HTTP POST routes + ```` or + ``/`` or + ``/`` or + ``//`` .. code:: python @@ -231,10 +231,10 @@ schemas `__ and associated to the methods using the following naming convention. For a method \`my_method\`: -- ``def _validator_my_method(self):`` will be called to get the schema - required to validate the input parameters. -- ``def _validator_return_my_method(self):`` if defined, will be called - to get the schema used to validate the response. +- ``def _validator_my_method(self):`` will be called to get the schema + required to validate the input parameters. +- ``def _validator_return_my_method(self):`` if defined, will be called + to get the schema used to validate the response. In order to offer even more flexibility, a new API has been developed. @@ -363,32 +363,33 @@ Changelog **Features** -- Add support for oauth2 security scheme in the Swagger UI. If your - openapi specification contains a security scheme of type oauth2, the - Swagger UI will display a login button in the top right corner. In - order to finalize the login process, a redirect URL must be provided - when initializing the Swagger UI. The Swagger UI is now initialized - with a oauth2RedirectUrl option that references a oauth2-redirect.html - file provided by the swagger-ui lib and served by the current addon. - (`#379 `__) +- Add support for oauth2 security scheme in the Swagger UI. If your + openapi specification contains a security scheme of type oauth2, the + Swagger UI will display a login button in the top right corner. In + order to finalize the login process, a redirect URL must be provided + when initializing the Swagger UI. The Swagger UI is now initialized + with a oauth2RedirectUrl option that references a + oauth2-redirect.html file provided by the swagger-ui lib and served + by the current addon. + (`#379 `__) 12.0.2.0.1 ---------- -- validator\_...() methods can now return a cerberus ``Validator`` - object instead of a schema dictionnary, for additional flexibility - (e.g. allowing validator options such as ``allow_unknown``). +- validator\_...() methods can now return a cerberus ``Validator`` + object instead of a schema dictionnary, for additional flexibility + (e.g. allowing validator options such as ``allow_unknown``). 12.0.2.0.0 ---------- -- Licence changed from AGPL-3 to LGPL-3 +- Licence changed from AGPL-3 to LGPL-3 12.0.1.0.1 ---------- -- Fix issue when rendering the jsonapi documentation if no documentation - is provided on a method part of the REST api. +- Fix issue when rendering the jsonapi documentation if no + documentation is provided on a method part of the REST api. 12.0.1.0.0 ---------- @@ -404,7 +405,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. @@ -419,8 +420,8 @@ Authors Contributors ------------ -- Laurent Mignon -- Sébastien Beau +- Laurent Mignon +- Sébastien Beau Maintainers ----------- @@ -435,6 +436,6 @@ 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. -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/base_rest/__init__.py b/base_rest/__init__.py index 431f67abd..16bd23e2e 100644 --- a/base_rest/__init__.py +++ b/base_rest/__init__.py @@ -1,3 +1,3 @@ -from . import models from . import components +from . import models from . import http diff --git a/base_rest/__manifest__.py b/base_rest/__manifest__.py index 755c27fe4..d80d6e39d 100644 --- a/base_rest/__manifest__.py +++ b/base_rest/__manifest__.py @@ -6,13 +6,13 @@ "summary": """ Develop your own high level REST APIs for Odoo thanks to this addon. """, - "version": "18.0.1.1.1", + "version": "19.0.1.0.0", "development_status": "Beta", "license": "LGPL-3", - "author": "ACSONE SA/NV, " "Odoo Community Association (OCA)", + "author": "ACSONE SA/NV, Odoo Community Association (OCA)", "maintainers": [], "website": "https://github.com/OCA/rest-framework", - "depends": ["component", "web"], + "depends": ["bus", "component", "web", "web_tour"], "data": [ "views/openapi_template.xml", "views/base_rest_view.xml", @@ -20,8 +20,16 @@ "assets": { "web.assets_frontend": [ "base_rest/static/src/scss/base_rest.scss", - "base_rest/static/src/js/swagger_ui.js", - "base_rest/static/src/js/swagger.js", + ], + "web.assets_tests": [ + "base_rest/static/tests/tours/**/*.js", + ], + "base_rest.assets_tour_openapi": [ + ("include", "web._assets_helpers"), + ("include", "web._assets_frontend_helpers"), + ("include", "web._assets_primary_variables"), + ("include", "web.assets_frontend"), + ("include", "web.assets_tests"), ], }, "external_dependencies": { @@ -33,5 +41,4 @@ "apispec", ] }, - "installable": False, } diff --git a/base_rest/components/service.py b/base_rest/components/service.py index b8611bcf2..ba10991d9 100644 --- a/base_rest/components/service.py +++ b/base_rest/components/service.py @@ -197,8 +197,7 @@ def _get_openapi_default_responses(self): return { "400": {"description": "One of the given parameter is not valid"}, "401": { - "description": "The user is not authorized. Authentication " - "is required" + "description": "The user is not authorized. Authentication is required" }, "404": {"description": "Requested resource not found"}, "403": { diff --git a/base_rest/controllers/api_docs.py b/base_rest/controllers/api_docs.py index 05a7d090c..8c5db9238 100644 --- a/base_rest/controllers/api_docs.py +++ b/base_rest/controllers/api_docs.py @@ -30,7 +30,7 @@ def index(self, **params): self._get_api_urls() primary_name = params.get("urls.primaryName") swagger_settings = { - "urls": self._get_api_urls(), + "urls": self._get_api_urls() or None, "urls.primaryName": primary_name, } values = {"swagger_settings": swagger_settings} diff --git a/base_rest/http.py b/base_rest/http.py index 71b3c8a18..4d28b1abf 100644 --- a/base_rest/http.py +++ b/base_rest/http.py @@ -29,8 +29,8 @@ ValidationError, ) from odoo.http import ( - CSRF_FREE_METHODS, MISSING_CSRF_WARNING, + SAFE_HTTP_METHODS, Dispatcher, SessionExpiredException, request, @@ -162,7 +162,7 @@ def dispatch(self, endpoint, args): # Check for CSRF token for relevant requests if ( - self.request.httprequest.method not in CSRF_FREE_METHODS + self.request.httprequest.method not in SAFE_HTTP_METHODS and endpoint.routing.get("csrf", True) ): token = params.pop("csrf_token", None) diff --git a/base_rest/models/rest_service_registration.py b/base_rest/models/rest_service_registration.py index 60e06fd3b..ea2155b7a 100644 --- a/base_rest/models/rest_service_registration.py +++ b/base_rest/models/rest_service_registration.py @@ -189,10 +189,10 @@ def build_registry(self, services_registry, states=None, exclude_addons=None): # dependencies to ensure that controllers defined in a more # specialized addon and overriding more generic one takes precedences # on the generic one into the registry - graph = odoo.modules.graph.Graph() - graph.add_module(self.env.cr, "base") + graph = odoo.modules.module_graph.ModuleGraph(self.env.cr) + graph.extend(["base"]) - query = "SELECT name " "FROM ir_module_module " "WHERE state IN %s " + query = "SELECT name FROM ir_module_module WHERE state IN %s " params = [tuple(states)] if exclude_addons: query += " AND name NOT IN %s " @@ -200,7 +200,7 @@ def build_registry(self, services_registry, states=None, exclude_addons=None): self.env.cr.execute(query, params) module_list = [name for (name,) in self.env.cr.fetchall() if name not in graph] - graph.add_modules(self.env.cr, module_list) + graph.extend(module_list) for module in graph: self.load_services(module.name, services_registry) diff --git a/base_rest/restapi.py b/base_rest/restapi.py index c9cf2c0e7..d7a75e93a 100644 --- a/base_rest/restapi.py +++ b/base_rest/restapi.py @@ -218,13 +218,13 @@ def from_params(self, service, params): validator = self.get_cerberus_validator(service, "input") if validator.validate(params): return validator.document - raise UserError(service.env._("BadRequest %s") % validator.errors) + raise UserError(service.env._("BadRequest %s", validator.errors)) def to_response(self, service, result): validator = self.get_cerberus_validator(service, "output") if validator.validate(result): return validator.document - raise SystemError(service.env._("Invalid Response %s") % validator.errors) + raise SystemError(service.env._("Invalid Response %s", validator.errors)) def to_openapi_query_parameters(self, service, spec): json_schema = self.to_json_schema(service, spec, "input") @@ -276,7 +276,7 @@ def get_cerberus_validator(self, service, direction): if isinstance(schema, dict): return Validator(schema, purge_unknown=True) raise Exception( - service.env._("Unable to get cerberus schema from %s") % self._schema + service.env._("Unable to get cerberus schema from %s", self._schema) ) def to_json_schema(self, service, spec, direction): @@ -412,7 +412,11 @@ def from_params(self, service, params): ) # multipart ony sends its parts as string except json.JSONDecodeError as error: raise ValidationError( - service.env._(f"{key}'s JSON content is malformed: {error}") + service.env._( + "%(key)s's JSON content is malformed: %(error)s", + key=key, + error=error, + ) ) from error param = part.from_params(service, json_param) params[key] = param diff --git a/base_rest/static/description/index.html b/base_rest/static/description/index.html index 11068ef2a..d8cb1d5d9 100644 --- a/base_rest/static/description/index.html +++ b/base_rest/static/description/index.html @@ -374,7 +374,7 @@

Base Rest

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! source digest: sha256:198b97806a0a8c480e6c8f26f3ce3199cba9978f8d152ecf93c80091323d1805 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

Beta License: LGPL-3 OCA/rest-framework Translate me on Weblate Try me on Runboat

+

Beta License: LGPL-3 OCA/rest-framework Translate me on Weblate Try me on Runboat

This addon is deprecated and not fully supported anymore from Odoo 16. Please migrate to the FastAPI migration module. See https://github.com/OCA/rest-framework/pull/291.

@@ -454,8 +454,8 @@

Usage

  • The method def search(self, **params) if defined, is accessible via the HTTP GET routes <string:_service_name>/ and <string:_service_name>/search.
  • -
  • The method def delete(self, _id) if defined, is accessible via the -HTTP DELETE route <string:_service_name>/<int:_id>.
  • +
  • The method def delete(self, _id) if defined, is accessible via +the HTTP DELETE route <string:_service_name>/<int:_id>.
  • The def update(self, _id, **params) method, if defined, is accessible via the HTTP PUT route <string:_service_name>/<int:_id>.
  • @@ -701,8 +701,9 @@

    16.0.1.0.2 (2023-10-07)

    Swagger UI will display a login button in the top right corner. In order to finalize the login process, a redirect URL must be provided when initializing the Swagger UI. The Swagger UI is now initialized -with a oauth2RedirectUrl option that references a oauth2-redirect.html -file provided by the swagger-ui lib and served by the current addon. +with a oauth2RedirectUrl option that references a +oauth2-redirect.html file provided by the swagger-ui lib and served +by the current addon. (#379) @@ -723,8 +724,8 @@

    12.0.2.0.0

    12.0.1.0.1

      -
    • Fix issue when rendering the jsonapi documentation if no documentation -is provided on a method part of the REST api.
    • +
    • Fix issue when rendering the jsonapi documentation if no +documentation is provided on a method part of the REST api.
    @@ -740,7 +741,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.

    @@ -767,7 +768,7 @@

    Maintainers

    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.

    -

    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/base_rest/static/tests/tours/tours_base_rest.esm.js b/base_rest/static/tests/tours/tours_base_rest.esm.js new file mode 100644 index 000000000..31efb8e14 --- /dev/null +++ b/base_rest/static/tests/tours/tours_base_rest.esm.js @@ -0,0 +1,35 @@ +import {registry} from "@web/core/registry"; + +registry + .category("web_tour.tours") + .add("base_rest.tour_api_docs_no_content_validation", { + steps: () => [ + { + trigger: "h4:contains('No API definition provided.')", + }, + ], + }); + +registry.category("web_tour.tours").add("base_rest.tour_api_docs_simple_api_endpoint", { + steps: () => [ + { + trigger: "span:contains('pod_bay_doors')", + }, + { + trigger: + "span.opblock-summary-path[data-path='/control-panel/pod_bay_doors/open']", + run: "click", + }, + { + trigger: "button.try-out__btn", + run: "click", + }, + { + trigger: "button.execute", + run: "click", + }, + { + trigger: "pre.microlight:contains('I'm sorry, Dave.')", + }, + ], +}); diff --git a/base_rest/tests/__init__.py b/base_rest/tests/__init__.py index ea99ebb9d..0ee2c7c49 100644 --- a/base_rest/tests/__init__.py +++ b/base_rest/tests/__init__.py @@ -1,4 +1,5 @@ from . import common +from . import test_api_docs from . import test_cerberus_list_validator from . import test_cerberus_validator from . import test_controller_builder diff --git a/base_rest/tests/common.py b/base_rest/tests/common.py index 427b4107b..94616d347 100644 --- a/base_rest/tests/common.py +++ b/base_rest/tests/common.py @@ -95,6 +95,7 @@ def _setup_registry(class_or_instance): ) # register our components + class_or_instance.comp_registry.load_components("component") class_or_instance.comp_registry.load_components("base_rest") # Define a base test controller here to avoid to have this controller @@ -239,15 +240,15 @@ def setUpClass(cls): class BaseRestCase(TransactionComponentCase, RegistryMixin): - @classmethod - def setUpClass(cls): - super().setUpClass() - cls.setUpRegistry() - cls.base_url = cls.env["ir.config_parameter"].get_param("web.base.url") - cls.registry.enter_test_mode(cls.env.cr) + # pylint: disable=W8106 + def setUp(self): + super().setUp() + self.setUpRegistry() + self.base_url = self.env["ir.config_parameter"].get_param("web.base.url") + self.registry_enter_test_mode(register_cleanup=False) # pylint: disable=W8110 @classmethod def tearDownClass(cls): - cls.registry.leave_test_mode() + cls.registry_leave_test_mode() super().tearDownClass() diff --git a/base_rest/tests/test_api_docs.py b/base_rest/tests/test_api_docs.py new file mode 100644 index 000000000..6fd75ad92 --- /dev/null +++ b/base_rest/tests/test_api_docs.py @@ -0,0 +1,79 @@ +from odoo.tests import HttpCase, tagged + +from odoo.addons.component.core import Component + +from .. import restapi +from .common import TransactionRestServiceRegistryCase + + +@tagged("post_install", "-at_install") +class TestAPIDocs(TransactionRestServiceRegistryCase, HttpCase): + @classmethod + def setUpClass(cls): + """ + Avoids shadowing of "base_url" from RegistyCase class. + """ + super().setUpClass() + cls.base_url = lambda _self: cls.env["ir.config_parameter"].get_param( + "web.base.url" + ) + + def setUp(self): + super().setUp() + + self._setup_registry(self) + + def tearDown(self): + self._teardown_registry(self) + + super().tearDown() + + def test_00_api_docs_no_data(self): + """ + Makes sure the API Swagger page doesn't crash when we have no active endpoints. + """ + self.authenticate("admin", "admin") + response = self.url_open("/api-docs") + + self.assertEqual(response.status_code, 200) + + # Verify the content through a tour. + self.start_tour( + "/api-docs", + "base_rest.tour_api_docs_no_content_validation", + login="admin", + ) + + def test_01_api_docs_simple_request(self): + """ + Adding a few controllers to the API, the Swagger interface should be fully + functional. We won't test it itself, only that Odoo is sending the + correct information. + """ + + class SimpleAPIEndpoint(Component): + _inherit = "base.rest.service" + _name = "simple.api.endpoint" + _usage = "api" + _collection = self._collection_name + _description = "Simple API Endpoint" + + @restapi.method( + [("/control-panel/pod_bay_doors/open", "POST")], + auth="public", + output_param=restapi.CerberusValidator( + {"result": {"type": "string", "required": True}} + ), + ) + def open_pod_bay_doors(self): + return {"result": "I'm sorry, Dave. I'm afraid I can't do that."} + + self._build_services(self, SimpleAPIEndpoint) + + self.authenticate("admin", "admin") + + self.start_tour( + "/api-docs", + "base_rest.tour_api_docs_simple_api_endpoint", + login="admin", + ) diff --git a/base_rest/tests/test_controller_builder.py b/base_rest/tests/test_controller_builder.py index 29b7ea8b3..7e360295f 100644 --- a/base_rest/tests/test_controller_builder.py +++ b/base_rest/tests/test_controller_builder.py @@ -33,7 +33,6 @@ def test_01(self): implementation, these routes where hardcoded into the base controller. """ - # pylint: disable=R7980 class TestServiceOldApi(Component): _inherit = "base.rest.service" _name = "test.ping.service" @@ -246,7 +245,6 @@ def test_02(self): required method to route the requests to the methods """ - # pylint: disable=R7980 class TestServiceNewApi(Component): _inherit = "base.rest.service" _name = "test.partner.service" @@ -340,7 +338,6 @@ def _get_partner_schema(self): def test_03(self): """Check that the controller builder takes care of services inheritance""" - # pylint: disable=R7980 class TestPartnerService(Component): _inherit = "base.rest.service" _name = "test.partner.service" @@ -467,7 +464,6 @@ def test_04(self): self._BaseTestController._default_csrf = default_csrf self._BaseTestController._default_save_session = default_save_session - # pylint: disable=R7980 class TestService(Component): _inherit = "base.rest.service" _name = "test.partner.service" @@ -584,7 +580,6 @@ def test_05(self): default_auth = "my_default_auth" self._BaseTestController._default_auth = default_auth - # pylint: disable=R7980 class TestService(Component): _inherit = "base.rest.service" _name = "test.partner.service" @@ -631,7 +626,6 @@ def test_06(self): default_auth = "my_default_auth" self._BaseTestController._default_auth = default_auth - # pylint: disable=R7980 class TestService(Component): _inherit = "base.rest.service" _name = "test.partner.service" diff --git a/base_rest/tests/test_openapi_generator.py b/base_rest/tests/test_openapi_generator.py index 92d60c2cf..f428be376 100644 --- a/base_rest/tests/test_openapi_generator.py +++ b/base_rest/tests/test_openapi_generator.py @@ -2,7 +2,7 @@ # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). from odoo.addons.component.core import Component -from odoo.addons.website.tools import MockRequest +from odoo.addons.http_routing.tests.common import MockRequest from .. import restapi from .common import TransactionRestServiceRegistryCase @@ -22,7 +22,6 @@ def tearDown(self): def test_01(self): """Simple test case""" - # pylint: disable=R7980 class PartnerService(Component): _inherit = "base.rest.service" _name = "test.partner.service" @@ -115,7 +114,6 @@ def test_02(self): we check that these parameters are into the openapi specification """ - # pylint: disable=R7980 class PartnerService(Component): _inherit = "base.rest.service" _name = "test.partner.service" @@ -185,7 +183,6 @@ def test_03(self): } ] - # pylint: disable=R7980 class PartnerService(Component): _inherit = "base.rest.service" _name = "test.partner.service" @@ -225,7 +222,6 @@ def _get_openapi_default_responses(self): def test_04(self): """Binary and Multipart form-data test case""" - # pylint: disable=R7980 class AttachmentService(Component): _inherit = "base.rest.service" _name = "test.attachment.service" diff --git a/base_rest/tests/test_service_context_provider.py b/base_rest/tests/test_service_context_provider.py index 22f826bb9..a2c45039c 100644 --- a/base_rest/tests/test_service_context_provider.py +++ b/base_rest/tests/test_service_context_provider.py @@ -1,7 +1,7 @@ # Copyright 2021 ACSONE SA/NV # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). from odoo.addons.component.core import Component -from odoo.addons.website.tools import MockRequest +from odoo.addons.http_routing.tests.common import MockRequest from .. import restapi from .common import BaseRestCase, TransactionRestServiceRegistryCase @@ -28,7 +28,6 @@ def test_01(self): no authenticated_partner_id """ - # pylint: disable=R7980 class TestServiceNewApi(Component): _inherit = "base.rest.service" _name = "test.partner.service" @@ -61,7 +60,6 @@ def test_02(self): authenticated_partner_id """ - # pylint: disable=R7880 class TestComponentContextprovider(Component): _name = "test.component.context.provider" _inherit = [ @@ -74,7 +72,6 @@ class TestComponentContextprovider(Component): "test_component_context_provider" ) - # pylint: disable=R7980 class TestServiceNewApi(Component): _inherit = "base.rest.service" _name = "test.partner.service" @@ -82,25 +79,37 @@ class TestServiceNewApi(Component): _collection = self._collection_name _description = "test" + def _get_partner_schema(self): + return {"name": {"type": "string", "required": True}} + @restapi.method( [(["//get", "/"], "GET")], output_param=restapi.CerberusValidator("_get_partner_schema"), auth="public", ) def get(self, _id): - return {"name": self.env["res.partner"].browse(_id).name} + return {"name": self.env["res.partner"].browse(_id).exists().name} self._build_components(TestComponentContextprovider) self._build_services(self, TestServiceNewApi) controller = self._get_controller_for(TestServiceNewApi) - service_component = controller().service_component + controller_instance = controller() + service_component = controller_instance.service_component with ( - MockRequest(self.env), + self.with_user("admin"), + MockRequest(self.env) as request, service_component(service_name="partner") as service, ): + # Required for logging REST methods. + request.httprequest.headers = {} self.assertEqual( service.work.authenticated_partner_id, self.env.user.partner_id.id ) + # Actually testing if the rules are computed correctly by calling + # the controller method itself. + controller_instance._process_method( + "partner", "get", self.env.user.company_id.partner_id.id + ) def test_03(self): """Test authenticated_partner_id @@ -109,7 +118,6 @@ def test_03(self): changes the authenticated_partner_id provided by the service context provider """ - # pylint: disable=R7880 class TestComponentContextprovider(Component): _name = "test.component.context.provider" _inherit = "base.rest.service.context.provider" @@ -122,7 +130,6 @@ def _get_authenticated_partner_id(self): "test_component_context_provider" ) - # pylint: disable=R7980 class TestServiceNewApi(Component): _inherit = "base.rest.service" _name = "test.partner.service" @@ -152,4 +159,4 @@ def get(self, _id): class CommonCase(BaseRestCase): # dummy test method to pass codecov def test_04(self): - self.assertEqual(self.registry.test_cr, self.cr) + self.assertEqual(self.registry.db_name, self.cr.dbname) diff --git a/base_rest/views/openapi_template.xml b/base_rest/views/openapi_template.xml index de42ff5b7..a27a0fb28 100644 --- a/base_rest/views/openapi_template.xml +++ b/base_rest/views/openapi_template.xml @@ -40,6 +40,9 @@ + + + =1.10.6 +apispec +cerberus fastapi>=0.110.0 parse-accept-language +pyquerystring python-multipart ujson