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
140 changes: 140 additions & 0 deletions fastapi_auth_partner/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
====================
Fastapi Auth Partner
====================

..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:2ebd9377ca7b035ab9fb0383513aacb5ca8645f69d5d85c171883b40b439017e
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

.. |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/18.0/fastapi_auth_partner
: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_partner
: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
:alt: Try me on Runboat

|badge1| |badge2| |badge3| |badge4| |badge5|

This module is the FastAPI implementation of
`auth_partner <../auth_partner>`__ it provides all the routes to manage
the authentication of partners.

**Table of contents**

.. contents::
:local:

Usage
=====

First you have to add the auth router to your FastAPI endpoint and the
authentication dependency to your app dependencies:

.. code:: python

from odoo.addons.fastapi import dependencies
from odoo.addons.fastapi_auth_partner.dependencies import (
auth_partner_authenticated_partner,
)
from odoo.addons.fastapi_auth_partner.routers.auth import auth_router

class FastapiEndpoint(models.Model):
_inherit = "fastapi.endpoint"

def _get_fastapi_routers(self):
if self.app == "myapp":
return [
auth_router,
]
return super()._get_fastapi_routers()

def _get_app_dependencies_overrides(self):
res = super()._get_app_dependencies_overrides()
if self.app == "myapp":
res.update(
{
dependencies.authenticated_partner_impl: auth_partner_authenticated_partner,
}
)
return res

Next you can manage your authenticable partners and directories in the
Odoo interface:

FastAPI > Authentication > Partner

and

FastAPI > Authentication > Directory

Next you must set the directory used for the authentication in the
FastAPI endpoint:

FastAPI > FastAPI Endpoint > myapp > Directory

Then you can use the auth router to authenticate your requests:

- POST /auth/register to register a partner
- POST /auth/login to authenticate a partner
- POST /auth/logout to unauthenticate a partner
- POST /auth/validate_email to validate a partner email
- POST /auth/request_reset_password to request a password reset
- POST /auth/set_password to set a new password
- GET /auth/profile to get the partner profile
- GET /auth/impersonate to impersonate a partner

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_auth_partner%0Aversion:%2018.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.

Credits
=======

Authors
-------

* Akretion

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

- `Akretion <https://www.akretion.com>`__:

- Sébastien Beau
- Florian Mounier

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.

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

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
4 changes: 4 additions & 0 deletions fastapi_auth_partner/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from . import models
from . import routers
from . import schemas
from . import wizards
33 changes: 33 additions & 0 deletions fastapi_auth_partner/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Copyright 2024 Akretion (http://www.akretion.com).
# @author Sébastien BEAU <[email protected]>
# @author Florian Mounier <[email protected]>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

{
"name": "Fastapi Auth Partner",
"summary": """This provides an implementation of auth_partner for FastAPI""",
"version": "18.0.1.0.0",
"license": "AGPL-3",
"author": "Akretion,Odoo Community Association (OCA)",
"website": "https://github.com/OCA/rest-framework",
"depends": [
"extendable_fastapi",
"auth_partner",
],
"data": [
"security/res_group.xml",
"security/ir_rule.xml",
"security/ir.model.access.csv",
"views/auth_partner_view.xml",
"views/auth_directory_view.xml",
"views/fastapi_endpoint_view.xml",
"wizards/wizard_auth_partner_impersonate_view.xml",
"wizards/wizard_auth_partner_reset_password_view.xml",
],
"demo": [
"demo/fastapi_endpoint_demo.xml",
],
"external_dependencies": {
"python": ["itsdangerous"],
},
}
29 changes: 29 additions & 0 deletions fastapi_auth_partner/demo/fastapi_endpoint_demo.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record model="fastapi.endpoint" id="fastapi_endpoint_demo">
<field name="name">Fastapi Auth Partner Demo Endpoint</field>
<field
name="description"
><![CDATA[
# A Dummy FastApi Partner Auth Demo

This demo endpoint has been created by inhering from "fastapi.endpoint", registering
a new app into the app selection field and implementing the `_get_fastapi_routers`
methods. See documentation to learn more about how to create a new app.
]]></field>
<field name="app">demo</field>
<field name="root_path">/fastapi_auth_partner_demo</field>
<field name="demo_auth_method">auth_partner</field>
<field name="user_id" ref="fastapi.my_demo_app_user" />
<field name="directory_id" ref="auth_partner.demo_directory" />
<field name="public_api_url">https://api.example.com/</field>
<field name="public_url">https://www.example.com/</field>
</record>

<record id="fastapi.my_demo_app_user" model="res.users">
<field
name="groups_id"
eval="[(4, ref('auth_partner.group_auth_partner_api'))]"
/>
</record>
</odoo>
68 changes: 68 additions & 0 deletions fastapi_auth_partner/dependencies.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Copyright 2024 Akretion (https://www.akretion.com).
# @author Sébastien BEAU <[email protected]>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

import logging
from typing import Annotated, Any

from itsdangerous import URLSafeTimedSerializer
from starlette.status import HTTP_401_UNAUTHORIZED

from odoo.api import Environment

from odoo.addons.base.models.res_partner import Partner
from odoo.addons.fastapi.dependencies import fastapi_endpoint, odoo_env
from odoo.addons.fastapi.models import FastapiEndpoint

from fastapi import Cookie, Depends, HTTPException, Request, Response

_logger = logging.getLogger(__name__)


Payload = dict[str, Any]


class AuthPartner:
def __init__(self, allow_unauthenticated: bool = False):
self.allow_unauthenticated = allow_unauthenticated

def __call__(
self,
request: Request,
response: Response,
env: Annotated[
Environment,
Depends(odoo_env),
],
endpoint: Annotated[FastapiEndpoint, Depends(fastapi_endpoint)],
fastapi_auth_partner: Annotated[str | None, Cookie()] = None,
) -> Partner:
if not fastapi_auth_partner and self.allow_unauthenticated:
return env["res.partner"].with_user(env.ref("base.public_user")).browse()

elif fastapi_auth_partner:
directory = endpoint.sudo().directory_id
try:
vals = URLSafeTimedSerializer(
directory.cookie_secret_key or directory.secret_key
).loads(fastapi_auth_partner, max_age=directory.cookie_duration * 60)
except Exception as e:
_logger.error("Invalid cookies error %s", e)
raise HTTPException(status_code=HTTP_401_UNAUTHORIZED) from e
if vals["did"] == directory.id and vals["pid"]:
partner = env["res.partner"].browse(vals["pid"]).exists()
if partner:
auth_partner = partner._get_auth_partner_for_directory(directory)
if auth_partner:
if directory.sliding_session:
helper = env["fastapi.auth.service"].new(
{"endpoint_id": endpoint}
)
helper._set_auth_cookie(auth_partner, request, response)
return partner
_logger.info("Could not determine partner from 'fastapi_auth_partner' cookie.")
raise HTTPException(status_code=HTTP_401_UNAUTHORIZED)


auth_partner_authenticated_partner = AuthPartner()
auth_partner_optionally_authenticated_partner = AuthPartner(allow_unauthenticated=True)
Loading
Loading