Skip to content
Merged
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
1 change: 1 addition & 0 deletions fastapi_user_manager/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"fastapi",
"pydantic",
],
"demo": ["demo/fastapi_endpoint_demo.xml"],
"data": [
"views/res_users_view.xml",
"views/fastapi_endpoint_view.xml",
Expand Down
2 changes: 1 addition & 1 deletion fastapi_user_manager/data/endpoint.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<odoo>
<odoo noupdate="1">
<record id="user_manager_endpoint" model="fastapi.endpoint">
<field name="name">User Manager</field>
<field name="app">user_manager</field>
Expand Down
58 changes: 58 additions & 0 deletions fastapi_user_manager/demo/fastapi_endpoint_demo.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?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>
<!-- This is the user that will be used to run the demo app -->
<record
id="my_demo_app_user_user"
model="res.users"
context="{'no_reset_password': True, 'no_reset_password': True}"
>
<field name="name">My Demo Endpoint User User</field>
<field name="login">my_demo_app_user_user</field>
<field name="groups_id" eval="[(6, 0, [])]" />
</record>

<!-- This is the group that will be used to run the demo app
This group will only depend on the "group_fastapi_endpoint_runner" group
that provides the minimal access rights to retrieve the user running the
endpoint handlers and performs authentication.
-->
<record id="my_demo_app_group" model="res.groups">
<field name="name">My Demo Endpoint Group User</field>
<field name="users" eval="[(4, ref('my_demo_app_user_user'))]" />
<field name="implied_ids" eval="[(4, ref('group_fastapi_endpoint_runner'))]" />
</record>

<!-- This is the endpoint that will be used to run the demo app
This endpoint will be registered on the "/fastapi_demo" path
-->

<record model="fastapi.endpoint" id="fastapi_endpoint_demo_user">
<field name="name">Fastapi Demo Endpoint user</field>
<field
name="description"
><![CDATA[
# A Dummy FastApi 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">user_manager</field>
<field name="root_path">/fastapi_user</field>
<field name="demo_auth_method">http_basic</field>
<field name="user_id" ref="my_demo_app_user_user" />
</record>

<!-- <record id="fastapi_endpoint_multislash_demo" model="fastapi.endpoint"> -->
<!-- <field name="name">Fastapi Multi-Slash Demo Endpoint</field> -->
<!-- <field name="description"> -->
<!-- Like the other demo endpoint but with multi-slash -->
<!-- </field> -->
<!-- <field name="app">demo</field> -->
<!-- <field name="root_path">/fastapi/demo-multi</field> -->
<!-- <field name="demo_auth_method">http_basic</field> -->
<!-- <field name="user_id" ref="my_demo_app_user" /> -->
<!-- </record> -->
</odoo>
2 changes: 1 addition & 1 deletion fastapi_user_manager/models/fastapi_endpoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ def api_key_based_authenticated_partner_impl(
env["res.users"]
.sudo()
.search([("api_key_user", "=", api_key)], limit=1)
.parner_id
.partner_id
)
if not partner:
raise HTTPException(
Expand Down
179 changes: 84 additions & 95 deletions fastapi_user_manager/routers/user.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from typing import Annotated

from odoo import api, models
from odoo.fields import Command

from odoo.addons.base.models.res_users import Users as ResUsers
from odoo.addons.fastapi.dependencies import (
Expand All @@ -10,54 +11,72 @@

from fastapi import APIRouter, Depends

from ..schemas.schemas import UserSc, UserScUpdate
from ..schemas.schemas import UserSc, UserScDel, UserScUpdate

# create a router
user_router = APIRouter(tags=["user"])


@user_router.post("/user")
@user_router.post("/user/create")
def create_user_data(
data: list[UserSc],
env: Annotated[api.Environment, Depends(odoo_env)],
partner: Annotated[api.Environment, Depends(authenticated_partner_env)],
) -> dict:
"""
create user personal data of authenticated user
"""

result = {}
for d in data:
user = env["res.users"].search(
["|", ("login", "=", d.login), ("login", "=", d.email)]
)
if user:
result[f"{user.name}"] = "No_modif"
else:
user = env["api.user.router"].create_user(d)
result[f"{user.name}"] = "New ok"

return result


@user_router.post("/user/update")
def update_user_data(
data: UserSc,
data: UserScUpdate,
env: Annotated[api.Environment, Depends(odoo_env)],
partner: Annotated[api.Environment, Depends(authenticated_partner_env)],
# user: Annotated[ResUsers, Depends(odoo_env)],
) -> UserSc:
):
"""
update user personal data of authenticated user
"""
user = env["res.users"].search(
[("name", "=", data.name), ("email", "=", data.email)]
# UserScUpdate.to_user_vals(data)
# helper = env["api.user.router"].new({"user": user})
updated_user = env["api.user.router"]._update_user(data)
if updated_user:
return "Update OK"
else:
return "No update, no user found"
#


@user_router.post("/user/archive")
def archive_user_data(
data: UserScDel,
env: Annotated[api.Environment, Depends(odoo_env)],
partner: Annotated[api.Environment, Depends(authenticated_partner_env)],
):
""" """
user_to_del = env["res.users"].search(
[
("login", "=", data.login),
]
)
if user:
return UserSc.from_res_user(user)
if user_to_del:
user_to_del.active = False
return "Archived user ok"
else:
vals = {
"name": data.name,
"login": data.email,
"phone": data.phone,
"mobile": data.mobile,
}
user = env["res.users"].create(vals)
return UserSc.from_res_user(user)
# helper = env["api.user.router"].new()
# user = helper.create(data)
# return UserSc.from_res_user(user)


# def update_user_data(
# data: UserScUpdate,
# env: Annotated[api.Environment, Depends(odoo_env)],
# # env: Annotated[api.Environment, Depends(authenticated_partner_env)],
# # user: Annotated[ResUsers, Depends(odoo_env)],
# ) -> ResUsers:
# """
# update user personal data of authenticated user
# """
# UserScUpdate.to_user_vals(data)
# helper = env["api.user.router"].new({"user": user})
# updated_user = helper._update_user(data)
# return UserSc.from_res_user(updated_user)
return "Error"


class ApiUserRouter(models.AbstractModel):
Expand All @@ -67,68 +86,38 @@ class ApiUserRouter(models.AbstractModel):
# user = fields.Many2one(comodel_name="res.users")

def _update_user(self, data: UserScUpdate) -> ResUsers:
self.ensure_one()
user = self.env["res.users"].search([("login", "=", data.login)])
values = self._get_user_values(data)
user = self.user
user.write(values)
# self._handle_shopinvader_customer_opt_in(data)
return user

def _create_user(self, data: UserSc) -> ResUsers:
self.ensure_one()
user = self.env["res.users"].search(
[("name", "=", data.name), ("email", "=", data.email)]
)
if user:
return user
else:
vals = {
"name": data.name,
"email": data.email,
"phone": data.phone,
"mobile": data.mobile,
}
user = self.env["res.users"].create(vals)
return user

# def _get_user_values(self, data: CustomerUpdate) -> dict:
# values = data.to_user_vals()
# lang_id = data.lang_id
# if bool(lang_id):
# values["lang"] = self.env["res.lang"].browse(lang_id).code
# return values


# @user_router.get("/users", response_model=list[UserInfo])
# def get_users(env: Annotated[Environment, Depends(odoo_env)]) -> list[UserInfo]:
# return [
# UserInfo(name=user.name, email=user.email or "")
# for user in env["res.users"].search([])
# ]


# @customer_router.get("/customer")
# def get_customer_data(
# partner: Annotated[ResPartner, Depends(authenticated_partner)],
# ) -> Customer:
# """
# Get customer personal data of authenticated user
# """
# return Customer.from_res_partner(partner)


# @customer_router.post(
# "/customer",
# )
# def update_customer_data(
# data: CustomerUpdate,
# env: Annotated[api.Environment, Depends(authenticated_partner_env)],
# partner: Annotated[ResPartner, Depends(authenticated_partner)],
# ) -> Customer:
# """
# update customer personal data of authenticated user
# """
# CustomerUpdate.to_res_partner_vals(data)
# helper = env["shopinvader_api_customer.router.helper"].new({"partner": partner})
# updated_partner = helper._update_shopinvader_customer(data)
# return Customer.from_res_partner(updated_partner)
def create_user(self, data: UserSc):
vals = {
"name": data.name,
"login": data.login,
"email": data.email,
"phone": data.phone,
"mobile": data.mobile,
}
company_id = self.env["res.company"].search([("name", "=", data.company)])
vals["company_id"] = company_id.id
if hasattr(self.env["res.users"], "role_ids"):
roles = self.env["res.users.role"].search([("name", "in", data.role)])
vals["role_line_ids"] = [
Command.create({"role_id": rol_id}) for rol_id in roles.ids
]
user = self.env["res.users"].create(vals)
user = self._post_process_user_creation(user, data.misc)
return user

def _post_process_user_creation(self, user, misc):
"""inherit it to adapt to your needs"""
if misc:
user = user.write(misc)
return user

def _get_user_values(self, data: UserScUpdate):
"""inherit it to adapt to your needs"""
values = data.misc
return values
21 changes: 16 additions & 5 deletions fastapi_user_manager/schemas/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@ class UserScUpdate(StrictExtendableBaseModel, extra="ignore"):
used to update user details
"""

name: str | None = None
mobile: str | None = None
opt_in: bool | None = None
lang_id: int | None = None
login: str | None = None
misc: dict | None = None

def to_user_vals(self) -> dict:
fields = self._get_user_update_fields()
Expand All @@ -22,6 +20,7 @@ def _get_user_update_fields(self):
"name",
"phone",
"mobile",
"misc",
]


Expand All @@ -30,10 +29,14 @@ class UserSc(StrictExtendableBaseModel):
used to get user details
"""

email: str
login: str
email: str | None = None
name: str | None = None
phone: str | None = None
mobile: str | None = None
company: str | None = None
role: list | None = None
misc: dict | None = None

@classmethod
def from_res_user(cls, odoo_rec):
Expand All @@ -42,4 +45,12 @@ def from_res_user(cls, odoo_rec):
name=odoo_rec.name or None,
phone=odoo_rec.phone or None,
mobile=odoo_rec.mobile or None,
compny=odoo_rec.company_id.name or None,
role=odoo_rec.role_id.name or None,
)


class UserScDel(StrictExtendableBaseModel):
email: str
name: str
login: str
1 change: 1 addition & 0 deletions fastapi_user_manager/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import test_fastapi_user_manager
Loading
Loading