Skip to content
Closed
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
4 changes: 2 additions & 2 deletions fastapi/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"name": "Odoo FastAPI",
"summary": """
Odoo FastAPI endpoint""",
"version": "18.0.1.3.0",
"version": "19.0.0.0.0",
"license": "LGPL-3",
"author": "ACSONE SA/NV,Odoo Community Association (OCA)",
"maintainers": ["lmignon"],
Expand All @@ -30,5 +30,5 @@
]
},
"development_status": "Beta",
"installable": False,
"installable": True,
}
26 changes: 13 additions & 13 deletions fastapi/dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
from odoo.api import Environment
from odoo.exceptions import AccessDenied

from odoo.addons.base.models.res_partner import Partner
from odoo.addons.base.models.res_users import Users
from odoo.addons.base.models.res_partner import ResPartner
from odoo.addons.base.models.res_users import ResUsers

from fastapi import Depends, Header, HTTPException, Query, status
from fastapi.security import HTTPBasic, HTTPBasicCredentials
Expand Down Expand Up @@ -35,29 +35,29 @@ def odoo_env(company_id: Annotated[int | None, Depends(company_id)]) -> Environm
yield env


def authenticated_partner_impl() -> Partner:
def authenticated_partner_impl() -> ResPartner:
"""This method has to be overriden when you create your fastapi app
to declare the way your partner will be provided. In some case, this
partner will come from the authentication mechanism (ex jwt token) in other cases
it could comme from a lookup on an email received into an HTTP header ...
See the fastapi_endpoint_demo for an example"""


def optionally_authenticated_partner_impl() -> Partner | None:
def optionally_authenticated_partner_impl() -> ResPartner | None:
"""This method has to be overriden when you create your fastapi app
and you need to get an optional authenticated partner into your endpoint.
"""


def authenticated_partner_env(
partner: Annotated[Partner, Depends(authenticated_partner_impl)],
partner: Annotated[ResPartner, Depends(authenticated_partner_impl)],
) -> Environment:
"""Return an environment with the authenticated partner id in the context"""
return partner.with_context(authenticated_partner_id=partner.id).env


def optionally_authenticated_partner_env(
partner: Annotated[Partner | None, Depends(optionally_authenticated_partner_impl)],
partner: Annotated[ResPartner | None, Depends(optionally_authenticated_partner_impl)],
env: Annotated[Environment, Depends(odoo_env)],
) -> Environment:
"""Return an environment with the authenticated partner id in the context if
Expand All @@ -69,9 +69,9 @@ def optionally_authenticated_partner_env(


def authenticated_partner(
partner: Annotated[Partner, Depends(authenticated_partner_impl)],
partner: Annotated[ResPartner, Depends(authenticated_partner_impl)],
partner_env: Annotated[Environment, Depends(authenticated_partner_env)],
) -> Partner:
) -> ResPartner:
"""If you need to get access to the authenticated partner into your
endpoint, you can add a dependency into the endpoint definition on this
method.
Expand All @@ -85,9 +85,9 @@ def authenticated_partner(


def optionally_authenticated_partner(
partner: Annotated[Partner | None, Depends(optionally_authenticated_partner_impl)],
partner: Annotated[ResPartner | None, Depends(optionally_authenticated_partner_impl)],
partner_env: Annotated[Environment, Depends(optionally_authenticated_partner_env)],
) -> Partner | None:
) -> ResPartner | None:
"""If you need to get access to the authenticated partner if the call is
authenticated, you can add a dependency into the endpoint definition on this
method.
Expand All @@ -110,7 +110,7 @@ def paging(
def basic_auth_user(
credential: Annotated[HTTPBasicCredentials, Depends(HTTPBasic())],
env: Annotated[Environment, Depends(odoo_env)],
) -> Users:
) -> ResUsers:
username = credential.username
password = credential.password
try:
Expand All @@ -137,9 +137,9 @@ def basic_auth_user(


def authenticated_partner_from_basic_auth_user(
user: Annotated[Users, Depends(basic_auth_user)],
user: Annotated[ResUsers, Depends(basic_auth_user)],
env: Annotated[Environment, Depends(odoo_env)],
) -> Partner:
) -> ResPartner:
return env["res.partner"].browse(user.sudo().partner_id.id)


Expand Down
4 changes: 2 additions & 2 deletions fastapi/models/fastapi_endpoint_demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from odoo.api import Environment
from odoo.exceptions import ValidationError

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

from fastapi import APIRouter, Depends, HTTPException, status
from fastapi.security import APIKeyHeader
Expand Down Expand Up @@ -90,7 +90,7 @@ def api_key_based_authenticated_partner_impl(
),
],
env: Annotated[Environment, Depends(odoo_env)],
) -> Partner:
) -> ResPartner:
"""A dummy implementation that look for a user with the same login
as the provided api key
"""
Expand Down
4 changes: 2 additions & 2 deletions fastapi/routers/demo_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from odoo.exceptions import AccessError, MissingError, UserError, ValidationError
from odoo.service.model import MAX_TRIES_ON_CONCURRENCY_FAILURE

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

from fastapi import APIRouter, Depends, File, HTTPException, Query, status
from fastapi.responses import JSONResponse
Expand Down Expand Up @@ -67,7 +67,7 @@ async def get_lang(env: Annotated[Environment, Depends(odoo_env)]):

@router.get("/demo/who_ami")
async def who_ami(
partner: Annotated[Partner, Depends(authenticated_partner)],
partner: Annotated[ResPartner, Depends(authenticated_partner)],
) -> DemoUserInfo:
"""Who am I?

Expand Down
5 changes: 1 addition & 4 deletions fastapi/security/res_groups.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,13 @@
<record id="group_fastapi_user" model="res.groups">
<field name="name">User</field>
<field name="implied_ids" eval="[(4, ref('base.group_user'))]" />
<field name="category_id" ref="module_category_fastapi" />
</record>

<record id="group_fastapi_manager" model="res.groups">
<field name="name">Administrator</field>
<field name="category_id" ref="module_category_fastapi" />
<field name="implied_ids" eval="[(4, ref('group_fastapi_user'))]" />
<field
name="users"
name="user_ids"
eval="[(4, ref('base.user_root')), (4, ref('base.user_admin'))]"
/>
</record>
Expand All @@ -28,6 +26,5 @@
the user running the endpoint handlers and performs authentication -->
<record id="group_fastapi_endpoint_runner" model="res.groups">
<field name="name">FastAPI Endpoint Runner</field>
<field name="category_id" ref="module_category_fastapi" />
</record>
</odoo>
12 changes: 6 additions & 6 deletions fastapi/tests/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
from odoo.tests import tagged
from odoo.tests.common import TransactionCase

from odoo.addons.base.models.res_partner import Partner
from odoo.addons.base.models.res_users import Users
from odoo.addons.base.models.res_partner import ResPartner
from odoo.addons.base.models.res_users import ResUsers

from fastapi import APIRouter, FastAPI
from fastapi.testclient import TestClient
Expand Down Expand Up @@ -80,8 +80,8 @@ def setUpClass(cls):
cls.default_fastapi_app: FastAPI | None = None
cls.default_fastapi_router: APIRouter | None = None
cls.default_fastapi_odoo_env: Environment = cls.env
cls.default_fastapi_running_user: Users | None = None
cls.default_fastapi_authenticated_partner: Partner | None = None
cls.default_fastapi_running_user: ResUsers | None = None
cls.default_fastapi_authenticated_partner: ResPartner | None = None
cls.default_fastapi_dependency_overrides: dict[
Callable[..., Any], Callable[..., Any]
] = {}
Expand All @@ -91,8 +91,8 @@ def _create_test_client(
self,
app: FastAPI | None = None,
router: APIRouter | None = None,
user: Users | None = None,
partner: Partner | None = None,
user: ResUsers | None = None,
partner: ResPartner | None = None,
env: Environment = None,
dependency_overrides: dict[Callable[..., Any], Callable[..., Any]] = None,
raise_server_exceptions: bool = True,
Expand Down
12 changes: 5 additions & 7 deletions fastapi/views/fastapi_endpoint.xml
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,11 @@
name="inactive"
domain="[('active','=',False)]"
/>
<group expand='0' string='Group by...'>
<filter
string='App'
name="groupby_app"
context="{'group_by': 'app'}"
/>
</group>
<filter
string='App'
name="groupby_app"
context="{'group_by': 'app'}"
/>
</search>
</field>
</record>
Expand Down
2 changes: 1 addition & 1 deletion fastapi/views/fastapi_menu.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@
<field name="name">FastAPI</field>
<field name="sequence" eval="400" />
<field name="web_icon">fastapi,static/description/icon.png</field>
<field name="groups_id" eval="[(4, ref('group_fastapi_user'))]" />
<field name="group_ids" eval="[(4, ref('group_fastapi_user'))]" />
</record>
</odoo>
Loading