Skip to content

Commit

Permalink
[ADD] shopinvader_fastapi_auth_partner_api_unit_member
Browse files Browse the repository at this point in the history
  • Loading branch information
paradoxxxzero committed Oct 18, 2024
1 parent db25c8c commit 0bcede4
Show file tree
Hide file tree
Showing 18 changed files with 1,005 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import setuptools

setuptools.setup(
setup_requires=['setuptools-odoo'],
odoo_addon=True,
)
67 changes: 67 additions & 0 deletions shopinvader_fastapi_auth_partner_api_unit_member/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
================================================
Shopinvader Fastapi Auth Partner Api Unit Member
================================================

..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:46bd8663388a1f03209619852bf7bec6c34a32457d19e688254400b19449d058
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |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-shopinvader%2Fodoo--shopinvader-lightgray.png?logo=github
:target: https://github.com/shopinvader/odoo-shopinvader/tree/16.0/shopinvader_fastapi_auth_partner_api_unit_member
:alt: shopinvader/odoo-shopinvader

|badge1| |badge2| |badge3|

This module glues the `shopinvader_fastapi_auth_partner_api` and the `shopinvader_api_unit_member` modules.

It adds a auth_state field to the unit member and defines this member route:

- `POST /unit/members/:id/invite` to add an auth.partner to the unit member allowing it to sign in and send an invite email to it.


**Table of contents**

.. contents::
:local:

Bug Tracker
===========

Bugs are tracked on `GitHub Issues <https://github.com/shopinvader/odoo-shopinvader/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/shopinvader/odoo-shopinvader/issues/new?body=module:%20shopinvader_fastapi_auth_partner_api_unit_member%0Aversion:%2016.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>`_:

* Florian Mounier

Maintainers
~~~~~~~~~~~

This module is part of the `shopinvader/odoo-shopinvader <https://github.com/shopinvader/odoo-shopinvader/tree/16.0/shopinvader_fastapi_auth_partner_api_unit_member>`_ project on GitHub.

You are welcome to contribute.
3 changes: 3 additions & 0 deletions shopinvader_fastapi_auth_partner_api_unit_member/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from . import models
from . import routers
from . import schemas
24 changes: 24 additions & 0 deletions shopinvader_fastapi_auth_partner_api_unit_member/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Copyright 2024 Akretion (http://www.akretion.com).
# @author Florian Mounier <[email protected]>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

{
"name": "Shopinvader Fastapi Auth Partner Api Unit Member",
"summary": "This module glues the shopinvader unit member management with "
"the fastapi auth partner api adding an auth state on members and an invite "
"route.",
"version": "16.0.1.0.0",
"license": "AGPL-3",
"author": "Akretion",
"website": "https://github.com/shopinvader/odoo-shopinvader",
"depends": [
"shopinvader_api_unit_member",
"shopinvader_fastapi_auth_partner",
],
"data": [
"data/email_data.xml",
"views/auth_directory_view.xml",
],
"auto_install": True,
"installable": True,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo noupdate="1">
<record id="email_already_existing" model="mail.template">
<field name="name">Auth Directory: Email Already Existing</field>
<field name="email_from">[email protected]</field>
<field name="subject">Someone tried to invite you in an other team</field>
<field name="partner_to">{{object.partner_id.id}}</field>
<field name="model_id" ref="auth_partner.model_auth_partner" />
<field name="auto_delete" eval="True" />
<field name="lang">{{object.partner_id.lang}}</field>
<field name="body_html" type="html">
<div>
Hi <t t-out="object.partner_id.name or ''" />
<t t-set="member" t-value="object.env.context.get('member')" />
<t t-set="manager" t-value="object.env.context.get('manager')" />

<p>
<t t-esc="manager.name" /> tried to invite you in the team
<t t-esc="manager.unit_id.name" /> but you already have an
other account, please contact <t t-esc="manager.name" /> if
you want to change your team.
</p>
</div>
</field>
</record>

</odoo>
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import auth_directory
from . import res_partner
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Copyright 2024 Akretion (http://www.akretion.com).
# @author Florian Mounier <[email protected]>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from odoo import fields, models


class AuthDirectory(models.Model):
_inherit = "auth.directory"

member_existing_template_id = fields.Many2one(
"mail.template",
"Mail Template Unit Member Already Existing",
required=False,
default=lambda self: self.env.ref(
"shopinvader_fastapi_auth_partner_api_unit_member.email_already_existing",
raise_if_not_found=False,
),
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Copyright 2024 Akretion (http://www.akretion.com).
# @author Florian Mounier <[email protected]>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import logging

from odoo import _, api, fields, models
from odoo.exceptions import UserError

from ..schemas import AuthState

_logger = logging.getLogger(__name__)


class ResPartner(models.Model):
_inherit = "res.partner"

member_auth_state = fields.Selection(
selection=[
(AuthState.none.value, "None"),
(AuthState.invited.value, "Invited"),
(AuthState.accepted.value, "Accepted"),
],
compute="_compute_member_auth_state",
compute_sudo=True,
)

@api.depends("auth_partner_ids.password", "auth_partner_ids.encrypted_password")
def _compute_member_auth_state(self):
for record in self:
auth = record.auth_partner_ids
if not auth:
record.member_auth_state = AuthState.none.value
continue

if len(auth) > 1:
_logger.warning(
"Multiple auth_partner_ids for unit member partner %s, "
"using the first one",
record,
)
auth = auth[0]

if auth.password or auth.encrypted_password:
record.member_auth_state = AuthState.accepted.value
else:
record.member_auth_state = AuthState.invited.value

@api.model
def _invite_shopinvader_unit_member(self, member_id, directory):
self._ensure_manager()
member = self.browse(member_id)
self._ensure_same_unit(member)
if not member.email:
raise UserError(_("Cannot invite a member without an email"))

auth_with_email = self.env["auth.partner"].search(
[
("login", "=", member.email),
("directory_id", "=", directory.id),
],
)

if auth_with_email:
# If another member with the same email is already in the directory,
if auth_with_email not in member.auth_partner_ids:
directory._send_mail_background(
"member_existing",
auth_with_email,
member=member,
manager=self,
)
raise UserError(
# Do not leak the information that the email is already in use
_("Something went wrong, please contact the administrator"),
)

member_auth = auth_with_email
else:
member_auth = self.env["auth.partner"].create(
{
"partner_id": member.id,
"login": member.email,
"directory_id": directory.id,
}
)

member_auth._send_invite()
return member
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
* `Akretion <https://www.akretion.com>`_:

* Florian Mounier
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
This module glues the `shopinvader_fastapi_auth_partner_api` and the `shopinvader_api_unit_member` modules.

It adds a auth_state field to the unit member and defines this member route:

- `POST /unit/members/:id/invite` to add an auth.partner to the unit member allowing it to sign in and send an invite email to it.

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .unit_members import unit_member_router
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Copyright 2024 Akretion (http://www.akretion.com).
# @author Florian Mounier <[email protected]>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from typing import Annotated

from fastapi import Depends

from odoo.addons.base.models.res_partner import Partner as ResPartner
from odoo.addons.fastapi.dependencies import fastapi_endpoint
from odoo.addons.fastapi.models import FastapiEndpoint
from odoo.addons.shopinvader_api_unit_member.routers import unit_member_router
from odoo.addons.shopinvader_api_unit_member.routers.unit_members import (
authenticated_manager,
)

from ..schemas import UnitMember


@unit_member_router.post("/unit/members/{member_id}/invite")
async def invite_unit_member(
partner: Annotated[ResPartner, Depends(authenticated_manager)],
endpoint: Annotated[FastapiEndpoint, Depends(fastapi_endpoint)],
member_id: int,
) -> UnitMember:
"""
Invite a unit member to sign in.
"""
member = partner._invite_shopinvader_unit_member(member_id, endpoint.directory_id)
return UnitMember.from_res_partner(member)
23 changes: 23 additions & 0 deletions shopinvader_fastapi_auth_partner_api_unit_member/schemas.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Copyright 2024 Akretion (http://www.akretion.com).
# @author Florian Mounier <[email protected]>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from enum import Enum

from odoo.addons.shopinvader_api_unit_member.schemas import UnitMember as UnitMemberBase


class AuthState(str, Enum):
none = "none"
invited = "invited"
accepted = "accepted"


class UnitMember(UnitMemberBase, extends=True):
auth_state: AuthState

@classmethod
def from_res_partner(cls, odoo_rec):
res = super().from_res_partner(odoo_rec)
res.auth_state = odoo_rec.member_auth_state
return res
Loading

0 comments on commit 0bcede4

Please sign in to comment.