Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
exclude: |
(?x)
# NOT INSTALLABLE ADDONS
^base_rest/|
^base_rest_auth_api_key/|
^base_rest_pydantic/|
^extendable/|
^pydantic/|
^rest_log/|
# END NOT INSTALLABLE ADDONS
# Files and folders generated by bots, to avoid loops
^setup/|/static/description/index\.html$|
Expand Down
14 changes: 9 additions & 5 deletions fastapi/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ Odoo FastAPI
: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/19.0/fastapi
:target: https://github.com/OCA/rest-framework/tree/20.0/fastapi
: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-19-0/rest-framework-19-0-fastapi
:target: https://translation.odoo-community.org/projects/rest-framework-20-0/rest-framework-20-0-fastapi
: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=19.0
:target: https://runboat.odoo-community.org/builds?repo=OCA/rest-framework&target_branch=20.0
:alt: Try me on Runboat

|badge1| |badge2| |badge3| |badge4| |badge5|
Expand Down Expand Up @@ -1636,7 +1636,7 @@ Bug Tracker
Bugs are tracked on `GitHub Issues <https://github.com/OCA/rest-framework/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 <https://github.com/OCA/rest-framework/issues/new?body=module:%20fastapi%0Aversion:%2019.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
`feedback <https://github.com/OCA/rest-framework/issues/new?body=module:%20fastapi%0Aversion:%2020.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.

Do not contact contributors directly about support or help with technical issues.

Expand All @@ -1647,12 +1647,16 @@ Authors
-------

* ACSONE SA/NV
* Open2S

Contributors
------------

- Laurent Mignon <laurent.mignon@acsone.eu>
- Lois Rilo <lois.rilo@forgeflow.com>
- Open2S (https://www.open2s.com.ec):

- Danilo Moya <danilo.moya@open2s.com.ec>

Maintainers
-----------
Expand All @@ -1675,6 +1679,6 @@ Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:

|maintainer-lmignon|

This module is part of the `OCA/rest-framework <https://github.com/OCA/rest-framework/tree/19.0/fastapi>`_ project on GitHub.
This module is part of the `OCA/rest-framework <https://github.com/OCA/rest-framework/tree/20.0/fastapi>`_ project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
12 changes: 5 additions & 7 deletions fastapi/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,16 @@

{
"name": "Odoo FastAPI",
"summary": """
Odoo FastAPI endpoint""",
"version": "19.0.1.1.0",
"summary": "Odoo FastAPI endpoint",
"version": "20.0.1.1.0",
"license": "LGPL-3",
"author": "ACSONE SA/NV,Odoo Community Association (OCA)",
"author": "ACSONE SA/NV, Open2S, Odoo Community Association (OCA)",
"maintainers": ["lmignon"],
"website": "https://github.com/OCA/rest-framework",
"depends": ["endpoint_route_handler"],
"data": [
"security/res_groups.xml",
"security/fastapi_endpoint.xml",
"security/ir_rule+acl.xml",
"security/ir.access.csv",
"views/fastapi_menu.xml",
"views/fastapi_endpoint.xml",
"views/fastapi_endpoint_demo.xml",
Expand All @@ -30,5 +28,5 @@
]
},
"development_status": "Beta",
"installable": False,
"installable": True,
}
4 changes: 2 additions & 2 deletions fastapi/demo/fastapi_endpoint_demo.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8" ?>
<?xml version="1.0" encoding="UTF-8" ?>
<!-- Copyright 2022 ACSONE SA/NV
License LGPL-3.0 or later (http://www.gnu.org/licenses/LGPL). -->
<odoo>
Expand Down Expand Up @@ -31,7 +31,7 @@
This endpoint will be registered on the "/fastapi_demo" path
-->

<record model="fastapi.endpoint" id="fastapi_endpoint_demo">
<record id="fastapi_endpoint_demo" model="fastapi.endpoint">
<field name="name">Fastapi Demo Endpoint</field>
<field
name="description"
Expand Down
2 changes: 1 addition & 1 deletion fastapi/depends.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@
stacklevel=2,
)

from .dependencies import * # noqa: F403, F401, E402
from .dependencies import *
7 changes: 6 additions & 1 deletion fastapi/fastapi_dispatcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@
from contextlib import contextmanager
from io import BytesIO

from odoo.http import Dispatcher, request
from odoo.http import request

try:
from odoo.http.dispatcher import Dispatcher
except ImportError:
from odoo.http import Dispatcher

from .context import odoo_env_ctx
from .error_handlers import convert_exception_to_status_body
Expand Down
15 changes: 5 additions & 10 deletions fastapi/models/fastapi_endpoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from collections.abc import Callable
from functools import partial
from itertools import chain
from typing import Any
from typing import Any, ClassVar

from starlette.middleware import Middleware
from starlette.routing import Mount
Expand Down Expand Up @@ -41,7 +41,6 @@ class FastapiEndpoint(models.Model):
app: str = fields.Selection(selection=[], required=True)
user_id = fields.Many2one(
comodel_name="res.users",
string="User",
help="The user to use to execute the API calls.",
default=lambda self: self.env.ref("base.public_user"),
)
Expand Down Expand Up @@ -82,7 +81,7 @@ def _clean_root_path(self):
root_path = "/" + root_path
return root_path

_blacklist_root_paths = {"/", "/web", "/website"}
_blacklist_root_paths: ClassVar[set[str]] = {"/", "/web", "/website"}

@api.constrains("root_path")
def _check_root_path(self):
Expand Down Expand Up @@ -141,7 +140,7 @@ def action_sync_registry(self):

def _handle_route_updates(self, vals):
observed_fields = [self._routing_impacting_fields(), self._fastapi_app_fields()]
refresh_fastapi_app = any([x in vals for x in chain(*observed_fields)])
refresh_fastapi_app = any(x in vals for x in chain(*observed_fields))
if refresh_fastapi_app:
self._reset_app()
if "user_id" in vals:
Expand Down Expand Up @@ -229,11 +228,7 @@ def _is_suburl(self, path, prefix) -> bool:
path = self._normalize_url_path(path)
prefix = self._normalize_url_path(prefix)

if path == prefix:
return True
if path.startswith(prefix + "/"):
return True
return False
return path == prefix or bool(path.startswith(prefix + "/"))

@api.model
def _find_first_matching_url_path(self, paths, prefix) -> str | None:
Expand Down Expand Up @@ -296,7 +291,7 @@ def _clear_fastapi_exception_handlers(self, app: FastAPI) -> None:
self._clear_fastapi_exception_handlers(route.app)

@api.model
@tools.ormcache("path")
@api.ormcache("path")
def get_uid(self, path):
record = self._get_endpoint(path)
if not record:
Expand Down
17 changes: 6 additions & 11 deletions fastapi/models/ir_rule.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,10 @@
from odoo import api, models


class IrRule(models.Model):
"""Add authenticated_partner_id in record rule evaluation context.
class IrAccess(models.Model):
"""Add authenticated_partner_id in record rule/access evaluation context."""

This come from the env current odoo environment which is
populated by dependency method authenticated_partner_env or authenticated_partner
when a route handler depends one of them and is called by the FastAPI service layer.
"""

_inherit = "ir.rule"
_inherit = "ir.access"

@api.model
def _eval_context(self):
Expand All @@ -22,6 +17,6 @@ def _eval_context(self):
)
return ctx

def _compute_domain_keys(self):
"""Return the list of context keys to use for caching ``_compute_domain``."""
return super()._compute_domain_keys() + ["authenticated_partner_id"]
def _get_access_context(self):
yield from super()._get_access_context()
yield self.env.context.get("authenticated_partner_id")
4 changes: 2 additions & 2 deletions fastapi/models/res_lang.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@

from accept_language import parse_accept_language

from odoo import api, models, tools
from odoo import api, models


class ResLang(models.Model):
_inherit = "res.lang"

@api.model
@tools.ormcache("accept_language")
@api.ormcache("accept_language")
def _get_lang_from_accept_language(self, accept_language):
"""Get the language from the Accept-Language header.

Expand Down
34 changes: 31 additions & 3 deletions fastapi/patch.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,18 @@

from urllib.parse import parse_qs, urlparse

from odoo.http import Request, db_filter
try:
import odoo.http.router as http_router
from odoo.http.requestlib import Request
from odoo.http.router import db_filter
except ImportError:
http_router = None
from odoo.http import Request, db_filter

_original_get_session_and_dbname = Request._get_session_and_dbname
_original_set_session_and_dbname = (
getattr(http_router, "_set_session_and_dbname", None) if http_router else None
)
_original_get_session_and_dbname = getattr(Request, "_get_session_and_dbname", None)


def _patched_get_session_and_dbname(self):
Expand All @@ -28,4 +37,23 @@ def _patched_get_session_and_dbname(self):
return session, dbname


Request._get_session_and_dbname = _patched_get_session_and_dbname
def _patched_set_session_and_dbname(request):
_original_set_session_and_dbname(request)
if not getattr(request, "db", None):
db = request.httprequest.args.get("db", "").strip()
if not db:
referer = request.httprequest.headers.get("Referer", "")
if referer:
parsed = urlparse(referer)
db = parse_qs(parsed.query).get("db", [""])[0].strip()
host = request.httprequest.environ.get("HTTP_HOST", "")
if db and db_filter([db], host=host):
request.db = db
if hasattr(request, "session") and request.session:
request.session.db = db


if _original_set_session_and_dbname is not None:
http_router._set_session_and_dbname = _patched_set_session_and_dbname
elif _original_get_session_and_dbname is not None:
Request._get_session_and_dbname = _patched_get_session_and_dbname
7 changes: 6 additions & 1 deletion fastapi/pools/fastapi_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,12 @@ def set_cache_sequence(self, key: str, value: int) -> None:
self.__cache_sequences[key] = value

def _check_cache(self, env: Environment) -> None:
cache_sequences = env.registry.cache_sequences
cache_sequences = getattr(env.registry, "cache_sequences", None)
if cache_sequences is None:
cache_sequences = {
k: v[0]
for k, v in getattr(env.registry, "registry_caches__", {}).items()
}
for key, value in cache_sequences.items():
if (
value != self.get_cache_sequence(key)
Expand Down
2 changes: 2 additions & 0 deletions fastapi/readme/CONTRIBUTORS.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
- Laurent Mignon \<<laurent.mignon@acsone.eu>\>
- Lois Rilo \<<lois.rilo@forgeflow.com>\>
- Open2S (https://www.open2s.com.ec):
- Danilo Moya \<<danilo.moya@open2s.com.ec>\>
9 changes: 8 additions & 1 deletion fastapi/routers/demo_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,14 @@

from odoo.api import Environment
from odoo.exceptions import AccessError, MissingError, UserError, ValidationError
from odoo.service.model import MAX_TRIES_ON_CONCURRENCY_FAILURE

try:
from odoo.http.retrying import MAX_TRIES_ON_CONCURRENCY_FAILURE
except ImportError:
try:
from odoo.service.model import MAX_TRIES_ON_CONCURRENCY_FAILURE
except ImportError:
MAX_TRIES_ON_CONCURRENCY_FAILURE = 5

from odoo.addons.base.models.res_partner import ResPartner

Expand Down
24 changes: 0 additions & 24 deletions fastapi/security/fastapi_endpoint.xml

This file was deleted.

6 changes: 6 additions & 0 deletions fastapi/security/ir.access.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
id,name,model_id,group_id/id,operation,domain
res_user_fastapi_running_user,Fastapi: Running user read users,res.users,fastapi.group_fastapi_endpoint_runner,r,"[('id', '=', user.id)]"
res_partner_fastapi_running_user,Fastapi: Running user read partners,res.partner,fastapi.group_fastapi_endpoint_runner,r,"['|', ('user_ids', '=', user.id), ('id', '=', authenticated_partner_id)]"
fastapi_endpoint_fastapi_running_user,Fastapi: Running user read endpoints,fastapi.endpoint,fastapi.group_fastapi_endpoint_runner,r,"[('user_id', '=', user.id)]"
fastapi_endpoint_access_view,fastapi.endpoint view,fastapi.endpoint,fastapi.group_fastapi_user,r,
fastapi_endpoint_access_manage,fastapi.endpoint manage,fastapi.endpoint,fastapi.group_fastapi_manager,crud,
Loading
Loading